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

MySQL 查詢優化實戰:索引失效 8 大場景與 SQL 重寫技巧

     編輯:MySQL 資料庫相關知識

索引失效八大「殺手」

#場景錯誤寫法正確寫法原理
1不等號(!=、<>)WHERE id != 2改用 WHERE id < 2 OR id > 2(仍難用索引),或應用層過濾範圍過大,優化器選全表掃描
2索引欄用函數WHERE DAY(regTime) = 6WHERE regTime >= '2023-01-06' AND regTime < '2023-01-07'函數破壞索引順序
3JOIN 欄位型別不一致ON u.id = c.userId (id=int, userId=varchar)統一型別、長度、編碼、UNSIGNED隱式轉換導致索引失效
4LIKE 以 % 開頭WHERE name LIKE '%abc'WHERE name LIKE 'abc%' 或全文索引B+ 樹無法從中間匹配
5低選擇性欄位建索引WHERE isNovice = 1 (只有 0/1,各 50%)不建索引,或組合索引 (isNovice, create_time)回表成本 > 全表掃描
6OR 條件未全覆蓋索引WHERE id=2 OR id=4 OR id=6WHERE id IN (2,4,6)IN 可走 range/ref,OR 易退化
7SELECT * 觸發回表SELECT * FROM t WHERE idx_col = 1SELECT id, col1 FROM t WHERE idx_col = 1(覆蓋索引)回表隨機 I/O 慢
8隱式型別轉換WHERE varchar_col = 123WHERE varchar_col = '123'字串轉數值,索引失效

SQL 重寫提速技巧

1. IN 代替 OR

-- 慢
SELECT * FROM t_user WHERE id = 2 OR id = 4 OR id = 6;
-- 快
SELECT * FROM t_user WHERE id IN (2, 4, 6);

2. 範圍查詢代替函數

-- 慢
SELECT * FROM t_user WHERE DATE(regTime) = '2010-02-01';
-- 快
SELECT * FROM t_user WHERE regTime >= '2010-02-01' AND regTime < '2010-02-02';

3. 運算下推到應用層

-- 慢:DB 做距離運算
SELECT userId, SQRT(POW(unitX,2)+POW(unitY,2)) AS distance FROM t_map_unit WHERE userId=2;
-- 快:只取座標,應用層算距離
SELECT userId, unitX, unitY FROM t_map_unit WHERE userId=2;

4. 拆解大 JOIN

-- 慢:大表 JOIN
SELECT c.*, u.name FROM t_user_city c LEFT JOIN t_user u ON u.id = c.userId;
-- 快:兩步查詢 + 應用層組裝
SELECT * FROM t_user_city;
SELECT name FROM t_user WHERE id IN (...);

原理:避免臨時表、減少鎖競爭、利用應用層記憶體與 CPU 平行處理。

深度優化:Oracle 風格規則在 MySQL 的適用性

  • IS NULL/IS NOT NULL: MySQL 可用索引(反例文所述),但 NULL 值不進入索引(除非為主鍵/唯一鍵)。
  • 連接欄位(||): MySQL 用 CONCAT(),同樣導致索引失效,拆成多欄等值最佳。
  • ORDER BY 非索引欄: 會觸發 filesort,建議建立 (where_col, order_col) 複合索引。

驗證清單

  1. EXPLAIN 確認 type != ALL。
  2. SHOW INDEX 確認索引存在且基數高。
  3. FLUSH STATUS; SELECT ...; SHOW SESSION STATUS LIKE 'Handler%'; 觀察 Handler_read_key vs Handler_read_rnd_next。
  4. 慢查詢日誌 + pt-query-digest 定期審視。

總結

索引失效多源於「破壞索引順序」(函數、運算、隱式轉換)或「選擇性不足」(低基數、大範圍)。掌握上述 8 大場景與 4 大重寫技巧,配合 EXPLAIN 驗證,能解決 90% 以上的慢查詢問題。記住:好的 SQL 是寫出來的,更是測出來的。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved