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


MySQL 5.6 リファレンスマニュアル  /  ...  /  MySQL のインデックスの使用の仕組み

8.3.1 MySQL のインデックスの使用の仕組み

インデックスは特定のカラム値のある行をすばやく見つけるために使用されます。インデックスがないと、MySQL は関連する行を見つけるために、先頭行から始めてテーブル全体を読み取る必要があります。テーブルが大きいほど、このコストが大きくなります。テーブルに問題のカラムのインデックスが含まれている場合、MySQL はすべてのデータを調べる必要なく、データファイルの途中のシークする位置をすばやく特定できます。これはすべての行を順次読み取るよりはるかに高速です。

ほとんどの MySQL インデックス (PRIMARY KEYUNIQUEINDEX、および FULLTEXT) は B ツリーに格納されます。例外: 空間データ型のインデックスは R ツリーを使用します。MEMORY テーブルはハッシュインデックスもサポートします。InnoDBFULLTEXT インデックスの逆のリストを使用します。

一般に、インデックスは次の説明に示すように使われます。ハッシュインデックス (MEMORY テーブルで使用されているような) に固有の特性については、セクション8.3.8「B ツリーインデックスとハッシュインデックスの比較」で説明しています。

MySQL はこれらの操作にインデックスを使用します。

  • WHERE 句に一致する行をすばやく見つけるため。

  • 行を考慮に入れないようにするため。複数のインデックスから選択する場合、MySQL は通常最小数の行を見つけるインデックス (もっとも選択的なインデックス) を使用します。

  • テーブルにマルチカラムインデックスがある場合、オプティマイザは、インデックスの左端のプリフィクスを使用して行をルックアップできます。たとえば、(col1, col2, col3) に 3 カラムのインデックスがある場合、(col1)(col1, col2)、および (col1, col2, col3) に対して、インデックス検索機能を使用できます。詳細については、セクション8.3.5「マルチカラムインデックス」を参照してください。

  • 結合の実行時に、ほかのテーブルから行を取得するため。カラムが同じ型とサイズで宣言されていると、MySQL はカラムのインデックスをより効率的に使用できます。このコンテキストでは、VARCHARCHAR は同じサイズで宣言されていれば同じとみなされます。たとえば、VARCHAR(10)CHAR(10) は同じサイズですが、VARCHAR(10)CHAR(15) は異なります。

    非バイナリ文字列カラム間での比較の場合、両方のカラムで同じ文字セットを使用しているべきです。たとえば、utf8 カラムと latin1 カラムの比較はインデックスの使用の可能性を否定します。

    異種のカラムの比較 (文字列カラムを時間または数値カラムと比較するなど) では、値を変換せずに直接比較できない場合、インデックスの使用が妨げられることがあります。数値カラム内の 1 などの特定の値の場合、'1'' 1''00001'、または '01.e1' などの文字列カラム内の任意の数の値と等しくなる可能性があります。これは、文字列カラムのインデックスの使用を除外します。

  • 特定のインデックス設定されたカラム key_col に対して、MIN() あるいは MAX() 値を見つけるため。これはインデックス内の key_col より前に発生するすべてのキーパートで、WHERE key_part_N = constant が使用されているかどうかをチェックするプリプロセッサによって最適化されます。この場合、MySQL は各 MIN() または MAX() 式に対して単一キールックアップを行い、それを定数で置き換えます。すべての式が定数で置き換えられた場合、クエリーは同時に返されます。例:

    SELECT MIN(key_part2),MAX(key_part2)
      FROM tbl_name WHERE key_part1=10;
    
  • 使用可能なインデックスの左端のプリフィクスに対してソートまたはグループ化が行われている場合 (たとえば、ORDER BY key_part1, key_part2) に、テーブルをソートまたはグループ化するため。すべてのキーパートのあとに DESC が付けられている場合、キーは逆の順序で読み取られます。セクション8.2.1.15「ORDER BY の最適化」およびセクション8.2.1.16「GROUP BY の最適化」を参照してください。

  • 場合によって、データ行を参照しないで値を取得するように、クエリーを最適化できます。(クエリーの必要なすべての結果を提供するインデックスは、カバーするインデックスと呼ばれます。)クエリーがテーブルから特定のインデックスに含まれるカラムのみを使用している場合、きわめて高速に、選択した値をインデックスツリーから取得できます。

    SELECT key_part3 FROM tbl_name
      WHERE key_part1=1
    

小さなテーブルまたは、レポートクエリーが行の大半またはすべてを処理する大きなテーブルに対するクエリーでは、インデックスはあまり重要ではありません。クエリーで行の大半にアクセスする必要がある場合は、順次読み取る方が、インデックスを処理するより高速です。クエリーですべての行が必要でない場合でも、順次読み取りは、ディスクシークを最小にします。詳細は、セクション8.2.1.20「フルテーブルスキャンを回避する方法」を参照してください。


User Comments
  Posted by Donny Simonton on November 4, 2003
Instead of using OR, just use IN. For example, you would write your query like:

select MembershipNumber, MemberID from Member where MemberID IN ('123896920', '1029540');

I'm running 4.1 currently and the difference between an OR and IN are nothing. But on an older 3.x box we have IN makes a huge difference.

  Posted by Peter Brodersen on June 7, 2004
Selecting data using OR on two different columns with individual indices could be optimized using UNION (thereby creating two separate queries). UNION was introduced in MySQL 4.0.

From the above example: (notice that two different fields are used - MemberID and MembershipNumber - if the field was the same, IN() or OR would be optimized)

Before:
select MembershipNumber, MemberID from Member where MemberID = 123896920 or MembershipNumber = 1029540;

After:
select MembershipNumber, MemberID from Member where MemberID = 123896920
UNION
select MembershipNumber, MemberID from Member where MembershipNumber = 1029540;

Two fast selects will be performed where indices are used. UNION will remove a possible duplicate (and UNION ALL would leave the duplicate).

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