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