當資料表很大且未儲存在儲存引擎的快取中時,在輔助索引上使用範圍掃描讀取資料列可能會導致對基底資料表進行多次隨機磁碟存取。透過磁碟掃描多範圍讀取 (MRR) 最佳化,MySQL 會嘗試減少範圍掃描的隨機磁碟存取次數,方法是先僅掃描索引並收集相關資料列的索引鍵。然後,索引鍵會排序,最後使用主鍵的順序從基底資料表擷取資料列。磁碟掃描 MRR 的動機是減少隨機磁碟存取的次數,並實現對基底資料表資料進行更連續的掃描。
多範圍讀取最佳化提供以下優點
MRR 能夠根據索引元組,依序而非隨機順序存取資料列。伺服器會取得一組滿足查詢條件的索引元組,根據資料列 ID 順序對其進行排序,並使用排序後的元組依序擷取資料列。這使得資料存取更有效率且成本更低。
MRR 能夠對需要透過索引元組存取資料列的操作,例如範圍索引掃描和使用索引進行聯結屬性的等值聯結,進行索引鍵存取的批次處理。MRR 會迭代一系列索引範圍,以取得符合資格的索引元組。隨著這些結果的累積,它們會被用來存取對應的資料列。在開始讀取資料列之前,不需要取得所有索引元組。
MRR 最佳化不支援在虛擬產生的資料行上建立的輔助索引。InnoDB
支援在虛擬產生的資料行上的輔助索引。
以下情境說明何時 MRR 最佳化可能有利
情境 A:MRR 可用於 InnoDB
和 MyISAM
資料表的索引範圍掃描和等值聯結操作。
一部分索引元組會累積在緩衝區中。
緩衝區中的元組會依其資料列 ID 排序。
資料列會根據排序後的索引元組順序存取。
情境 B:當執行多範圍索引掃描或按屬性執行等值聯結時,MRR 可用於 NDB
資料表。
一部分範圍 (可能是單鍵範圍) 會累積在提交查詢的中央節點的緩衝區中。
這些範圍會傳送到存取資料列的執行節點。
存取的資料列會封裝到封包中並傳回中央節點。
收到的資料列封包會放置在緩衝區中。
從緩衝區讀取資料列。
當使用 MRR 時,EXPLAIN
輸出的 Extra
資料行會顯示 Using MRR
。
如果不需要存取完整的資料表列來產生查詢結果,InnoDB
和 MyISAM
不會使用 MRR。如果結果完全可以根據索引元組中的資訊產生(透過覆蓋索引),則 MRR 不會提供任何好處。
兩個 optimizer_switch
系統變數標記提供了一個使用 MRR 優化的介面。mrr
標記控制是否啟用 MRR。如果 mrr
已啟用(on
),則 mrr_cost_based
標記控制最佳化工具是否嘗試在使用和不使用 MRR 之間做出基於成本的選擇(on
),或是在可能的情況下都使用 MRR(off
)。預設情況下,mrr
為 on
,而 mrr_cost_based
為 on
。請參閱第 10.9.2 節,「可切換的優化」。
對於 MRR,儲存引擎使用 read_rnd_buffer_size
系統變數的值作為其可以為緩衝區分配多少記憶體的指南。引擎最多使用 read_rnd_buffer_size
個位元組,並確定單次處理的範圍數量。