ケースA
クエリ:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
インデックス:
(thread_id, date_created)
予定:
Index is used
Using Where
Using filesort
そこに問題はありませんよね?インデックスが(WHERE
条件に部分的に一致するために)使用されている場合でも、結果を並べ替えるsome_column
(インデックスにない)ソート操作が必要です。また、2番目の条件に一致する行のみを保持するために、追加のチェック(Whereを使用)も必要です。OK。
ケースB(質問)
クエリ:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
インデックス:
(thread_id, date_created)
予定:
Index is used
Using Where
-- no "Using filesort"
では、なぜここでソートが必要ないのですか?なぜなら、インデックスはクエリが望むようにソートするのに十分だからです。もちろんAND placeholder = FALSE
、インデックスでカバーされていない追加の条件()の追加の問題があります。
わかりましたが、ここでは実際にソートは必要ありません。インデックスは、最初の条件(WHERE thread_id = 12345
)に一致し、出力に必要な順序である結果を提供します。必要な唯一の追加のチェック-プランが行うこと-は、インデックスから提供された順序でテーブルから行を取得し、20件の一致が得られるまでこの2番目の条件をチェックすることです。これが、「**使用場所」の意味です。
最初の20行(非常に良好で高速)、最初の100行(まだ十分高速である可能性が高い)、または最初の1000000(おそらく非常に遅い)で20件の一致を取得するか、インデックスから一致するすべての行を読み取った後でもテーブル(大きなテーブルでは実際には非常に遅い)。それはすべてデータの分布に依存します。
ケースC(さらに良い計画)
クエリ:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
インデックス:
(placeholder, thread_id, date_created)
予定:
Index is used
-- no "Using Where"
-- no "Using filesort"
これで、インデックスは条件と順序の両方に一致します。計画は非常に単純です。最初の* 20一致をインデックスから取得し、対応する行をテーブルから読み取ります。余分なチェック( "Using Where"は不要)とソート( "Using Filesort"は不要)は不要です。
first *:インデックスを最後から逆方向に読み取るときの最初の20(私たちのようにORDER BY .. DESC
)ですが、それは問題ではありません。Bツリーインデックスは、ほぼ同等のパフォーマンスで前方および後方に読み取ることができます。