Mysql 關於not exists一例
場景:
業務上需要做一個查詢,因為是Web及時響應,所以對響應時間有要求,原業務場景是需要從無庫存訂單中剔除繫結閒置庫存,因單條sql查詢實現複雜,故考慮用差集方式:
select a.col1, a.col2 from a where a.id = ? and not exists ( select b.id from b left join c on b.id = c.id where b.id = ? and b.id = a.id) order by a.id
資料量: a,b,c皆在百萬資料量級,排除其他非必要過濾欄位,id皆有btree索引
執行:2s左右
環境:阿里雲(最基本線上服務效能,資料庫執行狀態保持在10個以上鍊接)
分析:
原sql其實用的是not in,參考了 文章1 ,在同等資料量時not in 會走多次全表查詢(因為!=無對應索引),而not exists會走子查詢索引,所以not exists更快。故先用not exists替換了not in(語法有差異,替換時需要做b.id = a.id的關聯)。在參考 文章2 以後,嘗試用left join進行優化(其中關於mysql子查詢優化器說法待考量,後分析 文章3 ),改成如下方式:
select a.col1, a.col2 from a left join ( select b.id from b left join c on b.id = c.id where b.id = ? ) as r on a.id = r.id where b.id = ? and r.id is null order by a.id
思路便是先將子查詢符合的行通過left join查詢到,然後通過is null條件得到剩下的部分(即滿足需求的記錄)。最終執行時間在0.7s。
ref:
1. https://www.cnblogs.com/beijingstruggle/p/5885137.html
2. https://blog.csdn.net/zyz511919766/article/details/49335647
3. https://www.cnblogs.com/wxw16/p/6105624.html?utm_source=itdadao&utm_medium=referral