首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

高效能 MySQL SQL 編寫實戰:WHERE 子句索引失效模式、ORDER BY 陷阱、NOT/IN/EXISTS 優化與執行計畫分析

     編輯:MySQL 資料庫相關知識

核心原則:讓優化器用上索引

優化器根據統計資訊決定掃描策略。寫法不當導致索引失效 → 全表掃描 → 效能指數級下降。海量資料下,劣質 SQL 與優質 SQL 差距可達百倍。

六大索引失效模式與改寫

模式失效寫法根因優化寫法
IS NULL/IS NOT NULLWHERE col IS NULLB+ 樹不儲存 NULL (單列索引)預設值 + WHERE col = 'default'、或位圖索引 (其他引擎)
欄位運算/函數WHERE YEAR(date_col) = 2023索引存原始值,運算後無法匹配WHERE date_col >= '2023-01-01' AND date_col < '2024-01-01'
隱含型別轉換WHERE varchar_col = 123字串轉數字導致全掃描WHERE varchar_col = '123'
LIKE 通配符前置WHERE name LIKE '%abc%'無法利用索引前綴全文索引、前綴匹配 LIKE 'abc%'、應用層搜尋引擎
OR 跨欄位無聯合索引WHERE a=1 OR b=2無 (a,b) 聯合索引時各自掃描合併UNION ALL 分開查詢、或建立聯合索引
複合索引最左前綴違反索引 (a,b,c) 查 WHERE b=1未包含最左列 a補查 WHERE a=... AND b=1、或建 (b) 索引

ORDER BY 效能殺手

  • ORDER BY non_index_col → filesort (磁碟/記憶體排序)。
  • ORDER BY indexed_col DESC + LIMIT 10 → 反向掃描索引,極快。
  • ORDER BY expr(col) → 無法用索引。
  • 解決:覆蓋索引包含 ORDER BY 列、或應用層排序 (小結果集)。

NOT/!=/<> 索引失效

-- 失效
WHERE salary <> 5000
WHERE NOT (salary = 5000)

-- 可用索引 (範圍查詢)
WHERE salary < 5000 OR salary > 5000
-- 或應用層邏輯判斷

IN vs EXISTS:執行邏輯差異

現代優化器 (5.6+):自動將 IN 轉半連接、EXISTS 同等對待。建議統一用 EXISTS/NOT EXISTS,語意清晰、避免 NULL 陷阱。

實戰優化清單

  1. EXPLAIN FORMAT=JSON 觀察 access_type (ref/range/index/ALL)、key、rows、filtered。
  2. 覆蓋索引:SELECT id, name FROM t WHERE status=1 → 索引 (status, id, name) 避免回表。
  3. 延遲關聯:大表分頁 SELECT * FROM t ORDER BY id LIMIT 100000, 20 → SELECT * FROM t INNER JOIN (SELECT id FROM t ORDER BY id LIMIT 100000, 20) AS d USING (id)。
  4. 統計資訊鮮度:ANALYZE TABLE 定期更新,innodb_stats_persistent=ON。

結語

高效能 SQL 核心在於理解優化器決策邏輯、避開索引失效模式、善用覆蓋索引與延遲關聯。將 EXPLAIN 納入 Code Review 標準流程,每條上線 SQL 必須經過執行計畫審視,才能在海量資料下保持穩定高效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性IN (子查詢)EXISTS (相關子查詢)
執行順序先執行子查詢 → 物化結果集 → 外部查詢掃描匹配外部查詢驅動 → 每行執行子查詢 → 找到即停止
臨時表建立索引臨時表儲存子查詢結果無臨時表
適用場景子查詢結果極小、外部表大外部表小、子查詢有索引支援
NULL 陷阱NOT IN 含 NULL → 全假NOT EXISTS 安全