MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  B ツリーインデックスとハッシュインデックスの比較

8.3.9 B ツリーインデックスとハッシュインデックスの比較

B ツリーおよびハッシュデータ構造を理解することは、インデックスにこれらのデータ構造を使用するさまざまなストレージエンジンで (特に B ツリーインデックスを使用するか、ハッシュインデックスを使用するかを選択できる MEMORY ストレージエンジンの場合に)、さまざまなクエリーがどのように実行されるかを予測するのに役立つ可能性があります。

B ツリーインデックスの特性

B ツリーインデックスは =>>=<<=、または BETWEEN 演算子を使用する式で、カラム比較に使用できます。 このインデックスは、LIKE への引数がワイルドカード文字で始まらない定数文字列の場合の LIKE 比較にも使用できます。 たとえば、次の SELECT ステートメントはインデックスを使用します。

SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';

最初のステートメントでは、'Patrick' <= key_col < 'Patricl' の行のみが考慮されます。 2 つめのステートメントでは、'Pat' <= key_col < 'Pau' の行のみが考慮されます。

次の SELECT ステートメントはインデックスを使用しません。

SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE other_col;

最初のステートメントでは、LIKE 値はワイルドカード文字で始まります。 2 つめのステートメントでは、LIKE 値は定数ではありません。

... LIKE '%string%' を使用し、string が 3 文字より長い場合、MySQL は Turbo Boyer-Moore アルゴリズムを使用して、文字列のパターンを初期化してから、このパターンを使用して検索をより迅速に実行します。

col_name IS NULL を使用した検索では、col_name にインデックスが設定されている場合にインデックスが使用されます。

WHERE 句内のすべての AND レベルにまたがっていないインデックスは、クエリーの最適化に使用されません。 言い換えると、インデックスの使用を可能にするには、インデックスのプリフィクスがすべての AND グループで使用されている必要があります。

次の WHERE 句ではインデックスが使用されます。

... WHERE index_part1=1 AND index_part2=2 AND other_column=3

    /* index = 1 OR index = 2 */
... WHERE index=1 OR A=10 AND index=2

    /* optimized like "index_part1='hello'" */
... WHERE index_part1='hello' AND index_part3=5

    /* Can use index on index1 but not on index2 or index3 */
... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;

これらの WHERE 句ではインデックスが使用されません

    /* index_part1 is not used */
... WHERE index_part2=1 AND index_part3=2

    /*  Index is not used in both parts of the WHERE clause  */
... WHERE index=1 OR A=10

    /* No index spans all rows  */
... WHERE index_part1=1 OR index_part2=10

MySQL ではインデックスが使用できる場合でも使用しないことがあります。 これが発生する 1 つの状況は、オプティマイザが、インデックスを使用することによって MySQL がテーブルの大部分の行にアクセスする必要があると推定した場合です。 (この場合、必要なシークが少ないため、テーブルスキャンの方がはるかに高速になる可能性があります。) ただし、そのようなクエリーで、行の一部のみを取得する LIMIT を使用している場合、結果で返す少数の行をはるかにすばやく見つけることができるため、MySQL はとにかくインデックスを使用します。

ハッシュインデックスの特性

ハッシュインデックスは先述したものといくらか異なる特性を持ちます。

  • それらは、= または <=> 演算子を使用する等価比較にのみ使用されます (ただしきわめて高速です)。 それらは、値の範囲を見つける < などの比較演算子には使用されません。 この種類の単一値ルックアップに依存するシステムは、キー値ストアとして知られています。そのようなアプリケーションで MySQL を使用するには、可能なかぎりハッシュインデックスを使用します。

  • オプティマイザはハッシュインデックスを使用して、ORDER BY 操作を高速化することはできません。 (この種類のインデックスは順番に次のエントリを検索するために使用できません。)

  • MySQL は 2 つの値の間におよそどのくらいの行数があるかを判断できません (これは範囲オプティマイザによって使用するインデックスを特定するために使用されます)。 これは、MyISAM または InnoDB テーブルをハッシュインデックス設定された MEMORY テーブルに変更した場合に、一部のクエリーに影響することがあります。

  • 行の検索にはキー全体のみを使用できます。 (B ツリーインデックスでは、キーの任意の左端のプリフィクスを使用して行を検索できます。)


関連キーワード:  インデックス, テーブル, InnoDB, WHERE, ステートメント, ハッシュ, クエリー, ツリー, col, 結合