當資料表很大且未儲存在儲存引擎的快取中時,使用次要索引上的範圍掃描讀取資料列可能會導致對基礎資料表的多次隨機磁碟存取。透過磁碟掃描多範圍讀取 (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
位元組,並決定在單次傳遞中要處理的範圍數量。