sql >> データベース >  >> RDS >> Mysql

MySQLインデックスはどのように機能しますか?

    最初に知っておく必要があるのは、インデックスは、テーブル全体をスキャンして探している結果を取得することを回避する方法であるということです。

    さまざまな種類のインデックスがあり、それらはストレージレイヤーに実装されているため、それらの間に標準はなく、使用しているストレージエンジンにも依存します。

    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を比較するためにテーブルをヒットする必要があります フィールド。

    まとめ

    最適化について話したいときに考慮すべきいくつかの事実:

    1. 整数の比較は、文字列の比較よりもはるかに高速です。これは、 InnoDBでのハッシュインデックスのエミュレーションに関する例で説明できます。 。

    2. たぶん、プロセスにステップを追加すると、遅くなるのではなく、速くなります。これは、 SELECTを最適化できるという事実によって説明できます。 これを2つのステップに分割し、最初のステップで新しく作成されたメモリ内テーブルに値を格納してから、この2番目のテーブルでより重いクエリを実行します。

    MySQLには他のインデックスもありますが、B + Treeのものがこれまでで最も使用されており、ハッシュのものは知っておくとよいと思いますが、他のインデックスはMySQLドキュメント

    「HighPerformanceMySQL」の本を読むことを強くお勧めします。上記の答えは、間違いなくインデックスに関する章に基づいています。



    1. Linuxのカスタムキーストアで保護されたデータの使用

    2. PythonMySQLコネクタ-fetchoneの使用時に未読の結果が見つかりました

    3. rewriteBatchedStatements=trueを使用したMySQLおよびJDBC

    4. CASEおよびGROUPBYを使用したピボットの動的な代替手段