案例分析:mysql子查询,相关子查询特别小心

  
  
  案例分析:开发提了个订正更新数据的sql,一开始没注意看,就直接跑了,结果跑了半天,没动,静以为是在等锁,看线程状态是跑步的,那说明是没堵的,那就奇怪,为什么会跑半天,因为选择的结果集很快的,说明索引是没问题,于是中断了更新,准备分析下。
  先看看更新的语句:
  更新product_model
  设置内容=代替(内容、“productStatus”:“INIT”,“productStatus”:“DEDUCT_HOLD”)
  在biz_no (
  选择从fast_trade biz_no merchant_order_no (
  “000500101 ghwpjtdbw00”,
  “000500101 ghwpzu1tp00”,
  “000500101 ghwq01plh00”,
  “000500101 ghwq08t2p00”,
  “000500101 ghwq1apyt00”,
  “000500101 ghwq5jkfo00”,
  “000500101 ghwqqjisd00”,
  “000500101 ghwrq0erl00”,
  “000500201 ghngy24r000”,
  “000500201 ghwphg9r100”,
  “000500201 ghwpzm1jx00”,
  “000500201 ghwpzpfe100”,
  “000500201 ghwpztlup00”,
  “000500201 ghwpzui1100”,
  “000500201 ghwq0991p00”,
  “000500201 ghwr45qh200”,
  “000500201 ghwr64mxx00”,
  “000500201 ghwri2nkp00”
  ));
  
  
  分析更新语句:替换一个字段的值,用了子查询关联另外一张表。这个sql看起来没什么问题。然后查看了执行计划:
  
  
        

  点击()折叠或打开   

        
      <李>   解释
         李   <李>   ,,,,product_model
      李   <李>   ,,,,内容内容
      李   <李>   ,,,,biz_no
      李   <李>   ,,,,biz_no fast_trade merchant_order_no
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   
      李   <李>   id select_type分区possible_keys key_len过滤额外
      李   <李>   
      李   <李>   1 product_model 8 22101522 10000个临时
      李   <李>   2相关子查询fast_trade unique_subquery out_index 62 func 500
      李   <李>   
      李   <李>   2 000秒   李   
        
  
  结果吓死哥了,看到相关子查询任何人都淡定不了了吧…在看到22101522,哥差点吓出翔……
  相关子查询,可能有的人不是很清楚,稍微科普下。转述官方说法:子查询中的第一个选择、取决于外面的查询结果。换成人话就是说:子查询的查询方式依赖于外面的查询结果。用这个例子就是,先从product_model select *,得到一个结果集,本例就是22101522行。然后这个结果的每一行在跟fast_trade进行匹配,也就是说.product_model的2千多万行都与fast_trade的18行进行一次联合查询。一句话说清楚就是要执行2千多万次选择匹配操作。
  吓出翔了吧……实在是没搞懂mysql的更新是怎么优化的。
  为了进一步求证,我把更新改成了选择进行了一次执行计划:
  
  
        

  点击()折叠或打开   

        
      <李>   解释product_model
         李   <李>   ,,,,biz_no
      李   <李>   ,,,,biz_no fast_trade merchant_order_no
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李   <李>   ,,,,
      李

    案例分析:mysql子查询,相关子查询特别小心