セカンダリインデックスでの範囲スキャンを使用して行を読み取ると、テーブルが大きく、ストレージエンジンのキャッシュに格納されていない場合、ベーステーブルへのランダムディスクアクセスが多発する結果になることがあります。 Disk-Sweep Multi-Range Read (MRR) 最適化を使用すると、MySQL は、最初にインデックスだけをスキャンし、該当する行のキーを収集することによって、範囲スキャンのランダムディスクアクセスの回数を軽減しようとします。 続いてキーがソートされ、最後に主キーの順序を使用してベーステーブルから行が取得されます。 Disk-Sweep MRR の目的は、ランダムディスクアクセスの回数を減らし、その代わりに、ベーステーブルデータの順次スキャンを増やすことです。
Multi-Range Read の最適化には、次のメリットがあります。
MRR により、データ行はインデックスタプルに基づいて、ランダムな順序ではなく、順次アクセスできます。 サーバーはクエリー条件を満たすインデックスタプルセットを取得し、それらをデータ行 ID 順に従ってソートし、ソートされたタプルを使用して、データ行を順番に取得します。 これにより、データアクセスの効率が向上し、負荷が軽減されます。
MRR により、範囲インデックススキャンや結合属性にインデックスを使用する等価結合などの、インデックスタプル経由でのデータ行へのアクセスを必要とする操作のキーアクセスのリクエストのバッチ処理が可能になります。 MRR はインデックス範囲のシーケンスを反復処理して、対象のインデックスタプルを取得します。 これらの結果が累積されると、それらは対応するデータ行にアクセスするために使用されます。 データ行の読み取りを開始する前に、すべてのインデックスタプルを取得する必要はありません。
MRR 最適化は、仮想生成カラムに作成されたセカンダリインデックスではサポートされていません。 InnoDB
では、仮想生成カラムのセカンダリインデックスがサポートされます。
次のシナリオでは、MRR の最適化に利益がある場合について説明しています。
シナリオ A: インデックス範囲スキャンと等価結合操作で、InnoDB
テーブルと MyISAM
テーブルに対して MRR を使用できます。
インデックスタプルの一部はバッファーに累積されます。
バッファー内のタプルはそれらのデータ行 ID によってソートされます。
データ行には、ソートされたインデックスタプルシーケンスに従ってアクセスされます。
シナリオ B: 複数範囲インデックススキャンで、または属性によって等価結合を実行する際に、NDB
テーブルに対して、MRR を使用できます。
単一キー範囲の可能性のある範囲の一部は、クエリーが送信される中央ノード上のバッファーに累積されます。
範囲はデータ行にアクセスする実行ノードに送信されます。
アクセスされた行はパッケージに格納され、中央ノードに返送されます。
受け取ったデータ行を含むパッケージはバッファーに入れられます。
データ行がバッファーから読み取られます。
MRR が使用された場合は、EXPLAIN
出力の Extra
カラムに Using MRR
と示されます。
InnoDB
と MyISAM
は、クエリー結果を生成するために完全なテーブル行にアクセスする必要がない場合、MRR を使用しません。 これは、(カバーするインデックス経由で) インデックスタプル内の情報に完全に基づいて結果を生成できる場合であり、MRR にメリットはありません。
2 つの optimizer_switch
システム変数フラグは、MRR 最適化の使用へのインタフェースを提供します。 mrr
フラグは MRR を有効にするかどうかを制御します。 mrr
が有効 (on
) の場合、mrr_cost_based
フラグは、オプティマイザが MRR (on
) を使用するかどうか、または可能な場合は MRR (off
) を使用するかどうかを制御します。 デフォルトでは、mrr
は on
で、mrr_cost_based
は on
です。 セクション8.9.2「切り替え可能な最適化」を参照してください。
MRR では、ストレージエンジンが、そのバッファーに割り当てることができるメモリーの量のガイドラインとして、read_rnd_buffer_size
システム変数の値を使用します。 エンジンは最大 read_rnd_buffer_size
バイトを使用して、単一のパスで処理する範囲の数を判断します。