VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
行の検索の仕組み(とそれが高コストな理由)
通常のインデックス検索は 2 つのステップからなります。- MySQL はインデックスを検索して、どの行が一致するかを見つける
- 一致する各行について、MySQL はテーブルから完全な行を取得する(「行の検索」または「テーブルへの戻り検索」)
EXPLAIN でカバリングインデックスを見分ける
EXPLAIN は、カバリングインデックスが使われているときにそれを教えてくれます。Extra: Using index を探してください。EXPLAIN の出力にまだ慣れていない場合は、MySQL の EXPLAIN の読み方で主要な列をすべて説明しています。
Using index — MySQL はインデックスだけを読みました。行の検索はありません。
次に、インデックスに含まれない列を追加します。
Extra が空になりました。MySQL はインデックスを使って行を見つけ、次に order_total を得るために完全な行を取得します。行の検索が戻ってきました。
カバリングインデックスの設計
目標は、クエリが触れるすべての列(WHERE、ORDER BY、GROUP BY、および SELECT リスト内の列)を含めることです。列の順序は、WHERE と ORDER BY のフィルタリングについては引き続き左端プレフィックスのルールに従います。
user_idが最初 — 等価フィルタcreated_atが 2 番目 — ソート列(インデックスはすでに並んでいるため、filesort は不要)statusが最後 —SELECTにだけ含まれ、フィルタリングにもソートにも使われない
SELECT の列が最後に来るのは、それらがどの行が見つかるか、どの順序になるかに影響しないためです。ただ同乗しているだけです。
カバリングインデックスが価値を持つ場面
よくある質問
カバリングインデックスは SELECT * に役立ちますか?
いいえ。インデックスがクエリをカバーできるのは、SELECT リストのすべての列を含む場合だけです。SELECT * はすべての列を選択するため、すべての列をインデックス化する必要があります。その時点で、テーブルをインデックスとして実質的に複製したことになり、有用ではありません。
それでもカバリングインデックスは SELECT * のクエリを速くできますか?
はい、部分的には。MySQL が行の検索を行わなければならない場合でも、インデックスは取得する行を絞り込みます。改善は WHERE のフィルタリングから来るもので、行の検索をなくすことから来るものではありません。
カバリングインデックスが役立つかどうかはどう判断しますか?
EXPLAIN を実行して Extra を確認します。Using index condition が表示されるか、何も表示されず(Using index がなく)、rows が大きい場合、カバリングインデックスが役立つかもしれません。EXPLAIN ANALYZE は実際の行数と推定の行数を表示するため、オプティマイザの選択を確認するのに役立ちます。
トラブルシューティング
関連項目
- MySQL のインデックスの仕組み — カバリングインデックスの基礎となる B ツリーの基本
- MySQL の EXPLAIN の読み方 — EXPLAIN の出力で
Using indexを確認する方法 - InnoDB のデータ格納の仕組み — 行の検索が高コストである理由と、カバリングがそれを避ける理由