Documentation Home
MySQL 8.0 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 36.1Mb
PDF (A4) - 36.2Mb


このページは機械翻訳したものです。

8.9.4 インデックスヒント

インデックスヒントは、クエリー処理中にインデックスを選択する方法に関するオプティマイザ情報を提供します。 ここで説明するインデックスヒントは、セクション8.9.3「オプティマイザヒント」 で説明されているオプティマイザヒントとは異なります。 インデックスヒントとオプティマイザヒントは、別々に、または一緒に使用できます。

インデックスヒントは、SELECT および UPDATE ステートメントにのみ適用されます。

インデックスヒントは、テーブル名の後に指定します。 (SELECT ステートメントでテーブルを指定するための一般的な構文は、セクション13.2.10.2「JOIN 句」 を参照してください。) インデックスヒントを含む個々のテーブルを参照する構文は、次のようになります:

tbl_name [[AS] alias] [index_hint_list]

index_hint_list:
    index_hint [index_hint] ...

index_hint:
    USE {INDEX|KEY}
      [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
  | {IGNORE|FORCE} {INDEX|KEY}
      [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)

index_list:
    index_name [, index_name] ...

USE INDEX (index_list) ヒントは、名前付きインデックスのいずれかのみを使用してテーブル内の行を検索するように MySQL に指示します。 代替構文 IGNORE INDEX (index_list) は、特定のインデックスを使用しないように MySQL に指示します。 これらのヒントは、EXPLAIN によって、MySQL が可能性のあるインデックスのリストから間違ったインデックスを使用していることが示された場合に役立ちます。

FORCE INDEX ヒントは USE INDEX (index_list) のように機能しますが、テーブルスキャンは very コストが高いとみなされます。 つまり、テーブルスキャンは、名前付きインデックスのいずれかを使用してテーブル内の行を検索する方法がない場合にのみ使用されます。

注記

MySQL 8.0.20 の時点で、サーバーは、インデックスオプティマイザヒント JOIN_INDEX, GROUP_INDEX, ORDER_INDEX、および INDEX(NO_JOIN_INDEX, NO_GROUP_INDEX, NO_ORDER_INDEX および FORCE INDEX オプティマイザヒントに相当およびを置き替える)、および NO_INDEX オプティマイザヒント (IGNORE INDEX インデックスヒントに相当し、それらを置き換える) をサポートします。 したがって、USE INDEXFORCE INDEX および IGNORE INDEX は、MySQL の将来のリリースで非推奨になり、後で完全に削除される予定です。 詳細は、インデックスレベルのオプティマイザヒントを参照してください。

各ヒントには、カラム名ではなくインデックス名が必要です。 主キーを参照するには、PRIMARY という名前を使用します。 テーブルのインデックス名を表示するには、SHOW INDEX ステートメントまたは INFORMATION_SCHEMA.STATISTICS テーブルを使用します。

index_name 値は、完全なインデックス名である必要はありません。 インデックス名のあいまいでないプリフィクスにすることができます。 プリフィクスがあいまいな場合は、エラーが発生します。

例:

SELECT * FROM table1 USE INDEX (col1_index,col2_index)
  WHERE col1=1 AND col2=2 AND col3=3;

SELECT * FROM table1 IGNORE INDEX (col3_index)
  WHERE col1=1 AND col2=2 AND col3=3;

インデックスヒントの構文には、次の特性があります。

  • 構文的には、index_list for USE INDEX (「インデックスを使用しない」を意味する) を省略することが有効です。 index_list for FORCE INDEX または IGNORE INDEX の省略は構文エラーです。

  • ヒントに FOR 句を追加することで、インデックスヒントの有効範囲を指定できます。 これにより、クエリー処理の様々なフェーズの実行計画のオプティマイザ選択をよりきめ細かく制御できます。 MySQL がテーブル内の行の検索方法および結合の処理方法を決定するときに使用されるインデックスにのみ影響を与えるには、FOR JOIN を使用します。 行をソートまたはグループ化するためのインデックス使用に影響を与えるには、FOR ORDER BY または FOR GROUP BY を使用します。

  • 複数のインデックスヒントを指定できます。

    SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX FOR ORDER BY (i2) ORDER BY a;

    (同じヒント内であっても) 複数のヒントで同じインデックスに名前を付けるとエラーになりません:

    SELECT * FROM t1 USE INDEX (i1) USE INDEX (i1,i1);

    ただし、同じテーブルに対して USE INDEXFORCE INDEX を混在させると、エラーが発生します。

    SELECT * FROM t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2);

インデックスヒントに FOR 句が含まれていない場合、ヒントの有効範囲はステートメントのすべての部分に適用されます。 たとえば、次のヒント

IGNORE INDEX (i1)

は次のヒントの組み合わせと同等です。

IGNORE INDEX FOR JOIN (i1)
IGNORE INDEX FOR ORDER BY (i1)
IGNORE INDEX FOR GROUP BY (i1)

MySQL 5.0 では、FOR 句のないヒントスコープは、行の取得にのみ適用されました。 FOR 句が存在しないときにサーバーがこの古い動作を使用するようにするには、サーバーの起動時に old システム変数を有効にします。 レプリケーションセットアップでこの変数を有効にする場合は注意してください。 ステートメントベースのバイナリロギングでは、ソースとレプリカのモードが異なると、レプリケーションエラーが発生する可能性があります。

インデックスヒントが処理されるとき、これらのインデックスヒントは、型 (USEFORCEIGNORE) およびスコープ (FOR JOINFOR ORDER BYFOR GROUP BY) ごとに 1 つのリストに収集されます。 例:

SELECT * FROM t1
  USE INDEX () IGNORE INDEX (i2) USE INDEX (i1) USE INDEX (i2);

次と同等です。

SELECT * FROM t1
   USE INDEX (i1,i2) IGNORE INDEX (i2);

そのあと、インデックスヒントは、スコープごとに次の順序で適用されます。

  1. {USE|FORCE} INDEX が存在する場合は、これが適用されます。 (存在しない場合は、オプティマイザによって決定されたインデックスのセットが使用されます。)

  2. 前の手順の結果に対して、IGNORE INDEX が適用されます。 たとえば、次の 2 つのクエリーは同等です。

    SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) USE INDEX (i2);
    
    SELECT * FROM t1 USE INDEX (i1);

FULLTEXT の検索の場合、インデックスヒントは次のように機能します。

  • 自然言語モードの検索の場合、インデックスヒントは暗黙のうちに無視されます。 たとえば、IGNORE INDEX(i1) は警告なしで無視され、インデックスは引き続き使用されます。

  • ブールモードの検索の場合、FOR ORDER BY または FOR GROUP BY を含むインデックスヒントは暗黙のうちに無視されます。 FOR JOIN を含むインデックスヒント、または FOR 修飾子を含まないインデックスヒントは受け付けられます。 ヒントが FULLTEXT 以外の検索に適用される場合とは異なり、このヒントは、クエリー実行のすべてのフェーズ (行の検索と取得、グループ化、および順序付け) に使用されます。 これは、ヒントが FULLTEXT 以外のインデックスに対して指定されている場合でも当てはまります。

    たとえば、次の 2 つのクエリーは同等です。

    SELECT * FROM t
      USE INDEX (index1)
      IGNORE INDEX (index1) FOR ORDER BY
      IGNORE INDEX (index1) FOR GROUP BY
      WHERE ... IN BOOLEAN MODE ... ;
    
    SELECT * FROM t
      USE INDEX (index1)
      WHERE ... IN BOOLEAN MODE ... ;