最初に知っておく必要があるのは、インデックスは、テーブル全体をスキャンして探している結果を取得することを回避する方法であるということです。
さまざまな種類のインデックスがあり、それらはストレージレイヤーに実装されているため、それらの間に標準はなく、使用しているストレージエンジンにも依存します。
InnoDBとB+Treeインデックス
InnoDBの場合、最も一般的なインデックスタイプは、要素を並べ替えられた順序で格納するB+Treeベースのインデックスです。また、インデックス値を取得するために実際のテーブルにアクセスする必要がないため、クエリの戻りが速くなります。
このインデックスタイプの「問題」は、インデックスを使用するために左端の値をクエリする必要があることです。したがって、インデックスにlast_nameとfirst_nameの2つの列がある場合、これらのフィールドにクエリを実行する順序は非常に重要です 。
したがって、次の表が与えられます:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
このクエリはインデックスを利用します:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
しかし、次のものはそうではありません
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
first_name
をクエリしているため 最初に列があり、インデックスの左端の列ではありません。
この最後の例はさらに悪いです:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
これで、インデックスの右端のフィールドの右端の部分を比較しているためです。
ハッシュインデックス
これは、残念ながら、メモリバックエンドのみがサポートする別のインデックスタイプです。非常に高速ですが、完全なルックアップにのみ役立ちます。つまり、>
などの操作には使用できません。 、<
または
LIKE
。
これはメモリバックエンドでのみ機能するため、おそらくあまり頻繁には使用しません。私が今考えることができる主なケースは、別の選択からの結果のセットを使用してメモリに一時テーブルを作成し、ハッシュインデックスを使用してこの一時テーブルで他の多くの選択を実行するケースです。
大きなVARCHAR
がある場合 フィールドでは、別の列を作成し、その列に大きな値のハッシュを保存することで、Bツリーを使用するときにハッシュインデックスの使用を「エミュレート」できます。フィールドにURLを保存していて、値が非常に大きいとします。 url_hash
という整数フィールドを作成することもできます CRC32
のようなハッシュ関数を使用します または、URLを挿入するときにURLをハッシュするその他のハッシュ関数。そして、この値を照会する必要がある場合は、次のようにすることができます。
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
上記の例の問題は、 CRC32
関数は非常に小さなハッシュを生成し、ハッシュされた値で多くの衝突が発生することになります。正確な値が必要な場合は、次の手順でこの問題を修正できます。
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
衝突数が多い場合でも、ハッシュする価値はあります。これは、繰り返されるハッシュに対して2番目の比較(文字列1)のみを実行するためです。
残念ながら、この手法を使用すると、 url
を比較するためにテーブルをヒットする必要があります フィールド。
まとめ
最適化について話したいときに考慮すべきいくつかの事実:
-
整数の比較は、文字列の比較よりもはるかに高速です。これは、
InnoDB
でのハッシュインデックスのエミュレーションに関する例で説明できます。 。 -
たぶん、プロセスにステップを追加すると、遅くなるのではなく、速くなります。これは、
SELECT
を最適化できるという事実によって説明できます。 これを2つのステップに分割し、最初のステップで新しく作成されたメモリ内テーブルに値を格納してから、この2番目のテーブルでより重いクエリを実行します。
MySQLには他のインデックスもありますが、B + Treeのものがこれまでで最も使用されており、ハッシュのものは知っておくとよいと思いますが、他のインデックスはMySQLドキュメント 。
「HighPerformanceMySQL」の本を読むことを強くお勧めします。上記の答えは、間違いなくインデックスに関する章に基づいています。