Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 27.1Mb
PDF (A4) - 27.2Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


13.2.9.3 インデックスヒントの構文

クエリー処理中にインデックスを選択する方法に関する情報をオプティマイザに提供するためのヒントを指定できます。セクション13.2.9.2「JOIN 構文」では、SELECT ステートメントでテーブルを指定するための一般的な構文について説明しています。個々のテーブルの構文 (インデックスヒントの構文を含む) は次のようになります。

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 {INDEX|KEY}
      [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
  | FORCE {INDEX|KEY}
      [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)

index_list:
    index_name [, index_name] ...

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

また、USE INDEX (index_list) と同様の機能を持つが、テーブルスキャンが非常に負荷が大きいと見なされる点が追加された FORCE INDEX を使用することもできます。つまり、テーブルスキャンは、指定されたインデックスのいずれかを使用してテーブル内の行を検索する方法がない場合にのみ使用されます。

各ヒントには、カラムの名前ではなく、インデックスの名前が必要です。PRIMARY KEY の名前は PRIMARY です。テーブルのインデックス名を表示するには、SHOW INDEX を使用します。

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;

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

  • USE INDEX に空の index_list を指定する (つまり、インデックスを使用しない) ことは構文として有効です。FORCE INDEX または IGNORE INDEX に空の index_list を指定することは構文エラーです。

  • ヒントに FOR 句を追加することによって、インデックスヒントのスコープを指定できます。これにより、クエリー処理のさまざまなフェーズに対するオプティマイザの実行計画の選択をよりきめ細かく制御できるようになります。MySQL がテーブル内の行の検索方法および結合の処理方法を決定するときに使用されるインデックスにのみ影響を与えるには、FOR JOIN を使用します。行をソートまたはグループ化するためのインデックス使用に影響を与えるには、FOR ORDER BY または FOR GROUP BY を使用します。(ただし、テーブルを範囲に含むインデックスが存在し、それがテーブルへのアクセスに使用されている場合、オプティマイザは、そのインデックスを無効にする IGNORE INDEX FOR {ORDER BY|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)

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

インデックスヒントが処理されるとき、これらのインデックスヒントは、型 (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(i) は警告なしで無視され、インデックスが引き続き使用されます。

    ブールモードの検索の場合、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 ... ;

User Comments
  Posted by Igor Ivoilov on March 27, 2008
If you need to make select from 2 tables the syntax is

SELECT table1.*,table2.* FROM table1 USE INDEX (col2_index), table2 WHERE table1.col1=table2.col1 AND table1.col2=2 AND table1.col3=3;
  Posted by David Bennett on May 21, 2008
Due to an object relational layer that doesn't allow the specification of the index hint in the table_references declaration, I was forced into discovering an alternate technique. By specifying an indexes first column as the first where_condition I was able to force the optimizer to use the index that I wanted. In this case the index I wanted to use began with the 'edited' column (a datetime).

select * from appointment where edited < now() and ...

changed the optimizers index selection and greatly improved query performance.

  Posted by Ilan Hazan on November 15, 2010
The query analyzer is not perfect. An Optimizer that picks the wrong plan can cause severe performance issues.
However, this does NOT mean that you should always use a Force Index hint.
Read more at http://www.mysqldiary.com/the-battle-between-force-index-and-the-query-optimizer/

Sign Up Login You must be logged in to post a comment.