私はほとんどの開発者がするようにインデックスを使用します(主に...よく!インデックス)が、インデックスを使用してデータベースを最適化する多くの巧妙な方法があると確信しています。それがDBMSの実装に固有のものかどうかはわかりません。
私の質問は、インデックスの使用方法の基本的な例(基本的な明らかなケースを除く)と、テーブルにインデックスを指定したときにDBMSがデータベースをどのように最適化するかです。
インデックスを「目次」と考えてください...これは、ファイル内の位置へのポインタ(オフセット)の順序付きリストです。何百万ものレコードがテーブルに格納されているとすると、一致する条件をテーブルで検索するよりも、一致する順序付きリストを参照して、特定の一致する行へのポインタをスタックする方がはるかに高速です。インデックスの完全な例は、テーブルの主キーフィールド、最も一般的にはその「id」フィールドです。行ID#11234566が必要な場合は、データソースをスキャンして位置11234566をスキャンするよりも、データへのポインターをインデックスに要求する方がはるかに高速です。
インデックスの明確な使用法は次のとおりです。
CREATE TABLE activity_log (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
activity_type_id SMALLINT UNSIGNED NOT NULL,
datetime_created DATETIME
KEY(activity_type_id),
PRIMARY KEY(id)
);
CREATE TABLE activity_log_to_date_key (
activity_log_id INT UNSIGNED NOT NULL,
date_created_key INT UNSIGNED NOT NULL REFERENCES dim_datetime(id),
UNIQUE KEY(activity_log_id),
KEY(date_created_key)
);
CREATE TABLE dim_datetime (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
date_hour DATETIME NOT NULL,
PRIMARY KEY(id),
KEY(date_hour)
);
操作によってログレコードを作成できますが、ログテーブルよりも検索/並べ替えが高速なインデックス付き日時への参照を作成できます。次に、独自の主キーでログテーブルを結合します。これについて詳しく説明する必要がある場合は、お知らせください。これが理にかなっているといいのですが。
サンプルクエリ:
SELECT a.activity_log_id, al.activity_type_id, al.datetime_created
FROM activity_log_to_date_key a
INNER JOIN dim_datetime d ON (d.id = a.date_created_key)
LEFT JOIN activity_log al ON (al.id = a.activity_log_id)
WHERE d.date_hour BETWEEN '2009-01-01 00:00:00' AND '2009-06-01 12:00:00';
多くの人が見逃しているように見える1つの点は、DBMSはクエリ内のテーブル参照ごとに1つのインデックスのみを使用することが多い(または使用できる)ことであり、複数のインデックスを使用できる場合は、組み合わせて使用する方がおそらく高速です。存在する場合はインデックス。
たとえば、大きなテーブルで行WHERE AnIntegerColumn = 42 AND AnOtherInt = 69
を検索する場合、それらの行への最速ルートは、AnIntegerColumnとAnOtherIntの2つの列のインデックスになります。それぞれに個別のインデックスのみがあり、複合インデックスがない場合、DBはどちらか一方のインデックスを検索し、2番目の句で結果を個別にフィルター処理するか、両方をスキャンして結果を後で結合します。
複合インデックスで改善できるもう1つの一般的な単純な操作はWHERE SomeColumn = <SomeValue> ORDER BY SomeOtherColumn
です。SomeColumnとSomeOtherColumnに(正しい順序で)インデックスがある場合、状況によってはフィルタリング操作と順序付け操作を同時に実行できます。
インデックスを追加することは、最適化が不適切になる可能性があります。インデックスを格納するために使用される余分なスペース(および、DBが多くの書き込み操作を確認した場合にインデックスを維持するためのIO負荷)は、わずかに最適化されていない読み取りクエリよりも悪い問題になる可能性があるためです。 、無理しないでください。
デビッドとランディはこれをカバーしています。私はそれを追加したかっただけです EXPLAIN
コマンド は、インデックスの作成から大きな節約が得られる時期を理解し、必要なインデックスを提案するのに非常に役立ちます。クエリを実行するためにデータベースが実行しているステップが表示されるので、どのビットが最も時間がかかっているかがわかります。
ここで私がまだ言及していないことの1つは、複数のディスクがある場合、データが実際に存在する場所とは別のディスクにインデックスを配置することです。これにより、一部の操作を高速化できます。これはそれ自体が正解であるという点で疑問に値すると思います。