在項目開發中,同事在原本功能的基礎上加入了新的業務操作代碼后,導致業務操作經常超時。故對其代碼進行調試跟蹤后定位到,在update數據庫記錄時寫了in子查詢,完整sql如下(非原sql):
update wms_stock set qty1 = 0 where id in (select stock_id from wms_order_line l where l.a_qty1 = 'a' and l.product_code = 'b');
查看其執行計劃如下:
可以看到select_type存在DEPENDENT SUBQUERY,即子查詢依賴于外查詢。相當于將wms_stock表符合條件的數據(這里是全表)查出后,再拿內查詢去逐條匹配是否符合l.stock_id=s.id。故 整個update語句共需掃描233253*1=233253次。
MySql 官網給出的解決方法是:
If you have a slow 'correlated' subquery with IN, you can optimize it with a join to get around the bug described by Ryan and Stephen. After the optimization the execution time is no longer O(M×N).
按照上邊的思路我們將sql改為:
update wms_stock s join wms_order_line l on s.id = l.stock_id set s.qty1 = 0 where l.a_qty1 = 'a' and l.product_code = 'b';
再次查看執行計劃:
修改后問題成功解決。