1. 程式人生 > >【MySQL系列--優化3】——多範圍讀取優化

【MySQL系列--優化3】——多範圍讀取優化

在次級索引上使用範圍掃描讀取行可能會導致在表格較大並且未儲存在儲存引擎的快取記憶體中時對基表進行多次隨機磁碟訪問。通過磁碟掃描多範圍讀取(MRR)優化,MySQL嘗試通過首先掃描索引並收集相關行的金鑰來減少範圍掃描的隨機磁碟訪問次數。然後對金鑰進行排序,最後使用主鍵的順序從基表檢索行。磁碟掃描MRR的動機是減少隨機磁碟訪問的次數,從而對基表資料進行更順序的掃描。

多範圍讀取優化提供了以下好處:

  1. 基於索引元組,MRR使資料行可以順序訪問,而不是以隨機順序訪問。伺服器獲取一組滿足查詢條件的索引元組,根據資料行ID順序進行排序,並使用排序的元組依次檢索資料行。這使得資料訪問更加高效和更便宜。
  2. MRR允許對需要通過索引元組訪問資料行的操作進行金鑰訪問請求的批處理,例如範圍索引掃描和使用連線屬性的索引的等式連線。 MRR遍歷一系列索引範圍以獲得符合條件的索引元組。當這些結果累積時,它們被用於訪問相應的資料行。在開始讀取資料行之前,不必獲取所有索引元組。

在虛擬生成的列上建立的輔助索引不支援MRR優化。 InnoDB支援虛擬生成列上的輔助索引。

以下情況說明MRR優化可能是有利的:

場景A:MRR可用於InnoDB和MyISAM表,用於索引範圍掃描和等效連線操作。

  1. 索引元組的一部分被累積在緩衝器中。
  2. 緩衝區中的元組按其資料行ID排序
  3. 根據排序的索引元組序列訪問資料行。

場景B:MRR可用於多範圍索引掃描的NDB表,或者通過屬性執行等連線時。

  1. 範圍的一部分,可能是單鍵範圍,累積在提交查詢的中心節點上的緩衝區中。
  2. 範圍被髮送到訪問資料行的執行節點。
  3. 所訪問的行被打包到包中併發送回中心節點.
  4. 接收到的包含資料行的包將放置在緩衝區中。
  5. 從緩衝區中讀取資料行

使用MRR時,EXPLAIN輸出中的Extra列顯示使用MRR。

如果不需要訪問完整的錶行以產生查詢結果,InnoDB和MyISAM不使用MRR。如果結果可以完全基於索引元組中的資訊(通過覆蓋索引)生成,則是這種情況; MRR沒有任何好處。

假設在(key_part1,key_part2)上有一個索引,可以使用哪個MRR的示例查詢:

SELECT * FROM t
  WHERE key_part1 >= 1000 AND key_part1 < 2000
  AND key_part2 = 10000;

索引由(key_part1,key_part2)值的元組組成,首先由key_part1,然後由key_part2排序。

沒有MRR,索引掃描覆蓋了key_part1範圍從1000到2000的所有索引元組,而不管這些元組中的key_part2值。該掃描執行額外的工作,範圍內的元組包含除10000之外的key_part2值。

使用MRR,掃描被分解成多個範圍,每個範圍分別為key_part1(1000,1001,…,1999)的單個值。這些掃描中的每一個都只需要查詢key_part2 = 10000的元組。如果索引包含許多key_part2不是10000的元組,則MRR會導致讀取的索引元組少得多。

為了使用間隔符號表示,非MRR掃描必須檢查索引範圍[{1000,10000},{2000,MIN_INT}),其可能包括除了key_part2 = 10000之外的許多元組.MRR掃描檢查多個單點間隔[{1000,10000}],…,[{1999,10000}],其中僅包含key_part2 = 10000的元組。

兩個optimizer_switch系統變數標誌提供了使用MRR優化的介面。 mrr標誌控制是否啟用MRR。如果mrr啟用(on),那麼mrr_cost_based標誌控制優化器是否嘗試在使用和不使用MRR(on)之間進行基於成本的選擇,或者儘可能使用MRR(關閉)。預設情況下,mrr為on,mrr_cost_based為on。請參見第8.9.3節“可切換優化”。

對於MRR,儲存引擎使用read_rnd_buffer_size系統變數的值作為其緩衝區可以分配多少記憶體的指導。引擎最多使用read_rnd_buffer_size位元組,並確定單次傳遞中要處理的範圍數。