在 MySQL 5.0 版本中,使用 NOT IN 搭配靜態值列表時,大量資料下效能極差甚至產生錯誤結果:
-- 效能差、大數據下可能出錯
SELECT * FROM `table` WHERE id NOT IN (1,2,3,10000);
MySQL 5.0 正式支援子查詢,將靜態列表改為子查詢可穩定發揮效能:
-- 正確、適用大數據量
SELECT * FROM `table` WHERE id NOT IN (SELECT id FROM subtable);
| 寫法 | 適用場景 | 效能表現 |
|---|---|---|
NOT IN (值列表) | 小量靜態值 | 大數據時全表掃描、優化器難以使用索引 |
NOT IN (子查詢) | 動態/大量資料 | 優化器可轉為 Anti-Join,善用索引 |
實務上建議改用 NOT EXISTS 或 LEFT JOIN ... IS NULL,避免 NOT IN 遇到 NULL 值時的邏輯陷阱:
-- 方案 A:NOT EXISTS(語意清晰、效能穩定)
SELECT * FROM `table` t
WHERE NOT EXISTS (SELECT 1 FROM subtable s WHERE s.id = t.id);
-- 方案 B:LEFT JOIN + IS NULL(傳統高效寫法)
SELECT t.* FROM `table` t
LEFT JOIN subtable s ON s.id = t.id
WHERE s.id IS NULL;
NOT EXISTS/LEFT JOIN。NOT IN。NOT IN 子查詢回傳含 NULL 會導致整體結果為空,NOT EXISTS 無此問題。