1. 程式人生 > >MySQL查詢優化之索引合併

MySQL查詢優化之索引合併

原文地址:https://dev.mysql.com/doc/refman/5.7/en/index-merge-optimization.html

譯文:

8.2.1.3 索引合併優化

索引合併訪問方法使用多範圍掃描檢索行,並把檢索結果合併成一個。這種訪問方法僅合併來自單個表的索引掃描,而不是跨多個表的掃描。合併可以產生其底層掃描結果的並集、交集或交集的並集。

可能用到索引合併的查詢示例:

SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;

SELECT * FROM tbl_name
  WHERE (key1 = 10 OR key2 = 20) AND non_key = 30;

SELECT * FROM t1, t2
  WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%')
  AND t2.key1 = t1.some_col;

SELECT * FROM t1, t2
  WHERE t1.key1 = 1
  AND (t2.key1 = t1.some_col OR t2.key2 = t1.some_col2);

    Note

    索引合併優化演算法有如下已知的限制:

    1)如果你的查詢中有一個使用深度巢狀and/or的where子句,MySQL不會選擇最優計劃,而是會嘗試使用如下恆等變換來分散and/or:

(x AND y) OR z => (x OR z) AND (y OR z)
(x OR y) AND z => (x AND z) OR (y AND z)

    2)索引合併不適用於全文索引。

在explain的輸出結果中,索引合併的方法在型別列中顯示為index_merge。在這種情況下,key列包含一系列被使用的索引,key_len列包含所有這些索引中最長的索引。

索引合併優化有幾種演算法,顯示在explain輸出結果的extra列中:

    1)使用intersect(...)

    2)使用union(...)

    3)使用sort_union(...)

下面各部分內容更加詳細地描述了這些演算法。優化器基於不同選擇的成本估計選擇可能的索引合併演算法和其他訪問方法。

索引合併的使用取決於optimizer_switch系統變數的index_merge、index_merge_cross、index_merge_union和index_merge_sort_union這些標誌的值。這些標誌的預設值都是on,如果要使用某種具體的演算法,把index_merge的值設為off,把另外的標誌設定成允許的值。

索引合併交集訪問演算法

該訪問方法適用於where子句被轉換為不同索引鍵與and組合的多個範圍條件時,條件如下所示:

    1)如下所示形式的且由N部分組成的表示式,其中索引恰好有N個部分(也就是說,覆蓋了所有索引):

key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN

    2)任何作用於InnoDB表主鍵的範圍條件。

示例:

SELECT * FROM innodb_table WHERE primary_key < 10 AND key_col1 = 20;

SELECT * FROM tbl_name WHERE key1_part1 = 1 AND key1_part2 = 2 AND key2 = 2;

這種索引合併交集演算法對所有被使用的索引執行同步掃描,並且產生從合併索引的掃描中檢索出來的行序列交集。

如果查詢中使用的所有列都覆蓋有索引,則不會檢索出全錶行(在本例中,explain的輸出結果中在extra欄位裡顯示使用的索引)。下面就是這樣的一個查詢例子:

SELECT COUNT(*) FROM t1 WHERE key1 = 1 AND key2 = 1;

如果使用的索引沒有覆蓋查詢中的所有列,則只有在滿足所有使用的索引鍵的範圍條件時才會檢索全錶行。

如果合併條件之一是作用於InnoDB表主鍵的範圍條件,它不會用於行檢索,而是用於過濾使用其他條件檢索出的行。

索引合併並集訪問方法

這種演算法的標準與索引合併交集演算法相似。該訪問方法適用於表的where子句被轉換為不同索引鍵與or組合的多個範圍條件時,條件如下所示:

    1)如下所示形式的且由N部分組成的表示式,其中索引恰好有N個部分(也就是說,覆蓋了所有索引):

key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN

    2)任何作用於InnoDB表主鍵的範圍條件。

    3)索引合併交集演算法適用的條件

示例:

SELECT * FROM t1
  WHERE key1 = 1 OR key2 = 2 OR key3 = 3;

SELECT * FROM innodb_table
  WHERE (key1 = 1 AND key2 = 2)
     OR (key3 = 'foo' AND key4 = 'bar') AND key5 = 5;

索引合併排序並集訪問演算法

當表的where子句被轉換為不同索引鍵與or組合的多個範圍條件時,這種訪問演算法適用,但索引合併並集訪問演算法並不適用。

示例:

SELECT * FROM tbl_name
  WHERE key_col1 < 10 OR key_col2 < 20;

SELECT * FROM tbl_name
  WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col = 30;

排序並集演算法與並集演算法的不同之處在於排序並集演算法在返回行前必須先取出所有行的ID並根據ID排序。

PS:由於水平有限,譯文中難免存在謬誤,歡迎批評指正。