Mysql索引合并的實現(xiàn)示例
MySQL 中的索引合并是一種查詢優(yōu)化技術,當單個表查詢的 WHERE 子句中包含多個條件,并且這些條件分別可以用到不同的索引時,MySQL 優(yōu)化器可能會嘗試將這些索引掃描的結果合并起來,以更高效地獲取最終滿足所有條件的行。它本質(zhì)上是優(yōu)化器在無法找到最優(yōu)的單個復合索引時的一種“折衷”策略。
核心思想: 利用多個索引分別篩選數(shù)據(jù),然后將結果集合并(交集、并集或排序后并集)以得到最終結果,避免全表掃描。
一、索引合并的類型
MySQL 主要支持三種索引合并算法:
1.1 Index Merge Intersection Access (Using intersect(...)):
適用場景: WHERE 子句中的多個條件通過 AND 連接,并且每個條件都可以有效地使用一個單獨的索引(這些索引通常是單列索引)。
工作原理:優(yōu)化器對每個可用的索引執(zhí)行范圍掃描或等值查詢掃描。
- 獲取每個索引掃描得到的主鍵值(或行指針)集合。
 - 計算這些主鍵值集合的交集(即同時出現(xiàn)在所有集合中的主鍵值)。
 - 根據(jù)交集得到的主鍵值,回表(如果需要)讀取完整的行數(shù)據(jù)。
 
示例:
CREATE TABLE `t` ( `id` INT PRIMARY KEY, `a` INT, `b` INT, `c` VARCHAR(100), INDEX `idx_a` (`a`), INDEX `idx_b` (`b`) ); -- 假設 idx_a 和 idx_b 都是 B-Tree 索引 SELECT * FROM t WHERE a = 10 AND b = 20;
- 優(yōu)化器可能分別使用 
idx_a查找a=10的行(得到主鍵集合 S1)。 - 使用 
idx_b查找b=20的行(得到主鍵集合 S2)。 - 計算 S1 和 S2 的交集。
 - 根據(jù)交集結果回表取數(shù)據(jù)。
 - EXPLAIN 輸出: 
type列顯示index_merge,Extra列顯示Using intersect(idx_a, idx_b); Using where。 
1.2 Index Merge Union Access (Using union(...)):
適用場景: WHERE 子句中的多個條件通過 OR 連接,并且每個條件都可以有效地使用一個單獨的索引(這些索引通常是單列索引),并且查詢是 SELECT(非 UPDATE/DELETE),并且沒有使用 FOR UPDATE 或 LOCK IN SHARE MODE。
工作原理:
- 優(yōu)化器對每個可用的索引執(zhí)行范圍掃描或等值查詢掃描。
 - 獲取每個索引掃描得到的主鍵值(或行指針)集合。
 - 計算這些主鍵值集合的并集(即出現(xiàn)在任 意一個集合中的主鍵值)。
 - 對并集結果進行去重。
 - 根據(jù)去重后的主鍵值,回表(如果需要)讀取完整的行數(shù)據(jù)。
 
示例:
SELECT * FROM t WHERE a = 10 OR b = 20;
- 優(yōu)化器可能分別使用 
idx_a查找a=10的行(得到主鍵集合 S1)。 - 使用 
idx_b查找b=20的行(得到主鍵集合 S2)。 - 計算 S1 和 S2 的并集,并去重。
 - 根據(jù)去重后的結果回表取數(shù)據(jù)。
 - EXPLAIN 輸出: 
type列顯示index_merge,Extra列顯示Using union(idx_a, idx_b); Using where。 
1.3 Index Merge Sort-Union Access (Using sort_union(...)):
適用場景: WHERE 子句中的多個條件通過 OR 連接,但是這些條件無法直接使用 Index Merge Union(通常是因為索引掃描返回的是范圍結果,而不僅僅是點查詢的等值結果)。它是 Union 的一種變體,用于處理范圍掃描。
工作原理:
- 優(yōu)化器對每個可用的索引執(zhí)行范圍掃描。
 - 獲取每個索引掃描得到的主鍵值(或行指針)集合。
 - 對每個集合中的主鍵值分別排序。
 - 將排序后的多個主鍵值列表進行歸并排序,并在歸并過程中進行去重。
 - 根據(jù)歸并去重后的主鍵值,回表(如果需要)讀取完整的行數(shù)據(jù)。
 
示例:
SELECT * FROM t WHERE a < 10 OR b < 20; -- 或者 SELECT * FROM t WHERE a < 10 OR b = 20; -- 一個范圍,一個等值
- 優(yōu)化器使用 
idx_a掃描a < 10(得到主鍵集合 S1)。 - 使用 
idx_b掃描b < 20(或b = 20)(得到主鍵集合 S2)。 - 分別對 S1 和 S2 中的主鍵排序。
 - 對兩個有序列表進行歸并排序并去重。
 - 根據(jù)結果回表取數(shù)據(jù)。
 - EXPLAIN 輸出: 
type列顯示index_merge,Extra列顯示Using sort_union(idx_a, idx_b); Using where。 
二、索引合并的優(yōu)點
- 避免全表掃描: 當沒有單個復合索引可以覆蓋所有查詢條件時,索引合并提供了利用現(xiàn)有多個單列索引的可能性,避免代價高昂的全表掃描。
 - 利用現(xiàn)有索引: 如果表上已經(jīng)存在多個單列索引,優(yōu)化器可以嘗試利用它們,而不一定需要為特定查詢創(chuàng)建新的復合索引(盡管復合索引通常更好)。
 - 處理復雜 
OR條件: 對于OR連接的復雜條件,索引合并(特別是sort_union)提供了一種優(yōu)化的執(zhí)行路徑。 
三、索引合并的缺點與注意事項
通常不如復合索引高效:
- 額外開銷: 索引合并需要進行多個獨立的索引掃描、結果集的合并操作(交集、并集、排序歸并去重),這些操作本身就有開銷。
 - 多次回表: 合并操作是基于主鍵值進行的,最終得到主鍵集后,還需要根據(jù)這些主鍵值回表讀取完整的行數(shù)據(jù)(如果查詢需要的數(shù)據(jù)不在索引中)。而一個設計良好的復合索引可能直接覆蓋查詢(避免回表)或者按最有效的順序定位數(shù)據(jù)。
 - 優(yōu)化器成本估算可能不準: 合并多個索引的成本估算比使用單個復合索引更復雜,優(yōu)化器可能錯誤地選擇了索引合并,而實際上全表掃描或強制使用某個單索引可能更快(反之亦然)。
 
不是所有條件組合都適用:
- 只有特定的 
AND/OR結構且每個條件都能獨立使用索引時才可能觸發(fā)。 - 索引列類型、查詢條件的具體形式(等值、范圍、函數(shù)、隱式轉換)都會影響優(yōu)化器是否選擇索引合并。
 - 配置影響: 索引合并是否啟用受系統(tǒng)變量 
optimizer_switch控制。例如: 
-- 查看當前設置 SELECT @@optimizer_switch; -- 關閉所有索引合并優(yōu)化 SET optimizer_switch = 'index_merge=off'; -- 關閉特定類型的索引合并 (e.g., intersection) SET optimizer_switch = 'index_merge_intersection=off';
需要確認相關標志(index_merge, index_merge_intersection, index_merge_union, index_merge_sort_union)是開啟的 (on)。
統(tǒng)計信息準確性: 優(yōu)化器是否選擇索引合并以及選擇哪種合并算法,高度依賴于表的統(tǒng)計信息(如索引的基數(shù) cardinality)。過時的統(tǒng)計信息可能導致優(yōu)化器做出錯誤的選擇。
替代方案 - 優(yōu)先考慮復合索引:
- 最佳實踐: 對于經(jīng)常一起出現(xiàn)在 
WHERE子句中的列,尤其是通過AND連接的列,創(chuàng)建合適的復合索引通常是性能最優(yōu)的選擇。復合索引直接按索引順序定位滿足所有條件的行,避免了多索引掃描和合并的開銷,也更容易避免回表(如果索引覆蓋查詢)。 - 示例: 對于 
SELECT * FROM t WHERE a = 10 AND b = 20;,創(chuàng)建INDEX idx_a_b (a, b)或INDEX idx_b_a (b, a)通常會比依賴idx_a和idx_b的索引合并快得多。 
四、如何識別索引合并
使用 EXPLAIN 或 EXPLAIN FORMAT=JSON 查看查詢的執(zhí)行計劃:
type列: 顯示為index_merge。key列: 列出實際使用的索引,多個索引用逗號分隔(如idx_a, idx_b)。Extra列: 明確指出使用的合并算法:Using intersect(...)(交集)Using union(...)(并集)Using sort_union(...)(排序并集)
五、總結
MySQL 的索引合并(Index Merge)是一種在特定查詢條件下(涉及多個索引列且條件由 AND 或 OR 連接),優(yōu)化器利用多個獨立索引分別掃描數(shù)據(jù),然后對結果集進行交集、并集或排序后并集操作,最終定位目標行的優(yōu)化策略。
intersect處理AND條件。union/sort_union處理OR條件(sort_union處理范圍掃描)。
雖然索引合并提供了一種避免全表掃描的途徑,但它通常伴隨著額外的掃描、合并和回表開銷。創(chuàng)建合適的復合索引(Composite Index)通常是解決這類查詢性能問題的首選和更優(yōu)方案,因為它能更直接、高效地定位數(shù)據(jù)。
到此這篇關于Mysql索引合并的實現(xiàn)示例的文章就介紹到這了,更多相關Mysql索引合并內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
 mysql存儲過程 在動態(tài)SQL內(nèi)獲取返回值的方法詳解
本篇文章是對mysql存儲過程在動態(tài)SQL內(nèi)獲取返回值進行了詳細的分析介紹,需要的朋友參考下2013-06-06
 IDEA連接MySQL數(shù)據(jù)庫并執(zhí)行SQL語句使用數(shù)據(jù)圖文詳解
使用idea連接本地MySQL數(shù)據(jù)庫,就可以很方便的看到數(shù)據(jù)庫的內(nèi)容,還可以進行基本的增加,刪除,修改操作,下面這篇文章主要給大家介紹了關于IDEA連接MySQL數(shù)據(jù)庫并執(zhí)行SQL語句使用數(shù)據(jù)的相關資料,需要的朋友可以參考下2023-03-03
 重新restore了mysql到另一臺機器上后mysql 編碼問題報錯
重新restore了mysql到另一臺機器上,今天新寫了一個app,發(fā)現(xiàn)在admin界面下一添加漢字就會報錯2011-12-12
 MYSQL 創(chuàng)建函數(shù)出錯的解決方案
在程序開發(fā)過程中,大家有沒有遇到過mysql函數(shù)不能創(chuàng)建,我是遇到過,是一個很麻煩的問題,上網(wǎng)搜了些相關資料,整理在一起了,供大家參考,幫助那些需要幫助的朋友2015-08-08
 MySQL出現(xiàn)"Lock?wait?timeout?exceeded"錯誤的原因是什么詳解
這篇文章主要給大家介紹了關于MySQL出現(xiàn)"Lock?wait?timeout?exceeded"錯誤的原因是什么的相關資料,工作中同事遇到此異常,查找解決問題時,收集整理形成此篇文章,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-05-05
 云服務器Ubuntu_Server_16.04.1安裝MySQL并開啟遠程連接的方法
這篇文章主要介紹了云服務器Ubuntu_Server_16.04.1安裝MySQL并開啟遠程連接的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-02-02

