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