首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 優化器開關詳解:5.1/5.5/5.6 版本演進與實戰調優指南

     編輯:MySQL 綜合教學

背景:optimizer_switch 讓你掌控優化器

MySQL 5.1 引入 optimizer_switch 系統變量,通過開關控制優化器行為。5.5/5.6 陸續新增開關,至 5.6 達到 20+ 項。合理使用可繞過優化器缺陷、強制走最優路徑、排查執行計劃異常。

查看與修改

-- 查看當前開關
SHOW VARIABLES LIKE 'optimizer_switch';

-- 會話級修改 (推薦測試)
SET SESSION optimizer_switch='index_merge=off,mrr=on';

-- 全局修改 (需重啟持久化)
SET GLOBAL optimizer_switch='index_merge=off,mrr=on';

版本演進全景圖

MySQL 5.1 新增:Index Merge 系列

開關適用場景原理典型收益
index_merge_intersection多單列索引 AND 條件分別掃描索引,取 RowID 交集,回表避免全表掃描
index_merge_union多單列索引 OR 條件掃描所有相關索引,取 RowID 並集,回表OR 查詢加速
index_merge_sort_unionOR 條件 + 需排序Union 後按 RowID 排序,再回表減少 filesort

注意:Index Merge 適用於無組合索引、單列索引選擇率高場景。組合索引通常更優,優化器會自動選擇。

MySQL 5.5 新增:NDB 專用

開關作用
engine_condition_pushdownON:WHERE 條件下推到 Data Node 過濾後再發送到 SQL Node,大幅減少網絡傳輸。僅 NDB 引擎生效。

MySQL 5.6 新增:核心優化器重構

1. MRR (Multi-Range Read) 系列

開關核心機制適用場景收益
mrr範圍掃描時,按主鍵排序 RowID,順序回表大數據量範圍查詢,Buffer Pool 不足隨機 I/O → 順序 I/O,吞吐提升 2-10 倍
mrr_cost_based基於成本模型決定是否啟用 MRR默認 ON,優化器自動權衡避免小結果集 MRR 開銷

2. BKA (Batched Key Access)

開關機制前置條件
batched_key_accessJoin Buffer 掃描內表後,批量收集主鍵交給 MRR 接口一次性回表mrr=on + join_buffer_size 足夠

適用於 NLJ (Nested Loop Join) 內表大、需回表 場景,減少 Join Buffer 與存儲引擎交互次數。

3. BNL (Block Nested Loop)

開關機制收益
block_nested_loopJoin Buffer 記錄「是否匹配」標記,下輪外表值跳過已匹配行減少 CPU 比較次數,加速大表關聯

4. ICP (Index Condition Pushdown)

開關OFF (傳統)ON (ICP)收益
index_condition_pushdown組合索引 (A,B),僅用 A 定位,回表過濾 B索引樹內直接過濾 B,僅回表符合行減少回表 I/O,不改變掃描順序

經典案例:WHERE a=1 AND b LIKE 'xyz%',索引 (a,b),ICP 可在索引層過濾 b。

5. Use Index Extensions

開關原理適用
use_index_extensionsInnoDB 二級索引隱含主鍵列,優化器將索引 (c) 視為 (c, pk1, pk2...)查詢同時用到二級索引列與主鍵前綴列

6. Semi-Join 子查詢優化族

開關策略核心邏輯
semijoin總開關將 IN/EXISTS 子查詢轉為半連接,內表去重
firstmatchFirstMatch內表僅取第一匹配行,後續跳過
loosescanLooseScan按索引分組,每組取第一行
materialization物化表子查詢結果去重建臨時表+索引,外表關聯
subquery_materialization_cost_based成本決策基於成本選擇是否物化

半連接本質:SELECT * FROM a WHERE a.id IN (SELECT b.a_id FROM b) → 只關心 b 中「是否存在」匹配 a.id,不關心匹配幾行,故可去重。

實戰調優決策樹

  1. EXPLAIN 看到 Using temporary; Using filesort → 嘗試 mrr=on, batched_key_access=on(大表範圍/關聯)。
  2. OR 條件走全表掃描 → index_merge_union=on 或建組合索引。
  3. 子查詢極慢 → semijoin=on, materialization=on(5.6+ 默認開啟)。
  4. 組合索引回表多 → index_condition_pushdown=on(5.6+ 默認開啟)。
  5. NLJ 關聯大表 → block_nested_loop=on, batched_key_access=on + 增大 join_buffer_size。

避坑指南

  • 不要全局關閉 index_merge:某些場景它是唯一出路,建議會話級測試。
  • MRR 需足夠 join_buffer_size/read_rnd_buffer_size:內存不足會退化性能。
  • ICP 不支持全文/空間索引,不支持覆蓋索引查詢(無回表)。
  • Semi-Join 物化表無統計信息:優化器可能誤估行數,導致次優計劃。
  • 版本差異:5.6 默認開啟 mrr/icp/semijoin/materialization;5.7/8.0 進一步完善成本模型。

總結

optimizer_switch 是 DBA 手中的「微調旋鈕」。理解每個開關的適用邊界、前置條件、副作用,結合 EXPLAIN 與實測,才能在優化器「犯迷糊」時精準糾偏。建議:默認保持開啟,會話級關閉/開啟驗證,效果確定再全局固化。

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