web-dev-qa-db-ja.com

MySQL問題で複数列インデックスのフィールドの順序を実行しますか

インデックスの重要性と、結合の順序によってパフォーマンスがどのように変わるかを知っています。私は複数列のインデックスに関連するたくさんの読書をしましたが、私の質問に対する答えが見つかりませんでした。

複数列のインデックスを作成する場合、それらが指定される順序がまったく重要である場合、私は興味があります。私の推測では、そうではなく、エンジンはそれらをグループとして扱い、順序は関係ありません。しかし、私は確認したいと思います。

たとえば、mysqlのWebサイトから( http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

CREATE TABLE test (
    id         INT NOT NULL,
    last_name  CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (last_name,first_name)
);

次の方が良い場合はメリットがありますか、それとも同等ですか?

CREATE TABLE test (
    id         INT NOT NULL,
    last_name  CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (first_name,last_name)
);

具体的には:

INDEX name (last_name,first_name)

INDEX name (first_name,last_name)
41
James Oravec

複数列のインデックスについて説明するとき、私は電話帳に類似しています。電話帳は基本的に姓、次に名のインデックスです。したがって、ソート順は、どの「列」が最初かによって決まります。検索はいくつかのカテゴリに分類されます。

  1. 姓がSmithの人を検索すると、本が姓でソートされているため、簡単に見つけることができます。

  2. ジョンという名の人を検索すると、ジョンが本の中に散在しているため、電話帳は役に立ちません。それらをすべて見つけるには、電話帳全体をスキャンする必要があります。

  3. 特定の姓がSmithで特定の名がJohnの人を検索すると、スミスが一緒に並べ替えられていることがわかり、そのスミスのグループ内ではJohnも並べ替えられた順序で見つかります。

電話帳を名でソートしてから姓でソートした場合、ブックのソートは上記のケース#2と#3では役立ちますが、ケース#1では役立ちません。

これは正確な値を検索する場合を説明していますが、値の範囲で検索している場合はどうでしょうか。姓がJohnで始まり、姓が「S」で始まるすべての人を検索したいとします(Smith、Saunders、Staunton、Shermanなど)。ジョンは姓ごとに「J」の下でソートされますが、「S」で始まるすべての姓のすべてのジョンが必要な場合、ジョンはグループ化されません。それらは再び散在しているため、姓が「S」で始まるすべての名前をスキャンする必要があります。電話帳が姓、名の順に編成されている場合、すべてのジョンが一緒に検索され、ジョン内ではすべての「S」の姓がグループ化されます。

したがって、マルチカラムインデックスのカラムの順序は間違いなく重要です。 1つのタイプのクエリでは、インデックスに特定の列の順序が必要な場合があります。複数のタイプのクエリがある場合、列を異なる順序で使用して、それらを助けるためにいくつかのインデックスが必要になる場合があります。

詳細については、私のプレゼンテーション インデックスの設計方法、本当に を参照してください。

71
Bill Karwin

2つのインデックスは異なります。これはMySQLと他のデータベースに当てはまります。 MySQLは documentation の違いをかなりうまく説明しています。

次の2つのインデックスについて考えます。

create index idx_lf on name(last_name, first_name);
create index idx_fl on name(first_name, last_name);

これらはどちらも同じように機能します。

where last_name = XXX and first_name = YYY

idx_lfは、次の条件に最適です。

where last_name = XXX
where last_name like 'X%'
where last_name = XXX and first_name like 'Y%'
where last_name = XXX order by first_name

idx_flは次の場合に最適です。

where first_name = YYY
where first_name like 'Y%'
where first_name = YYY and last_name like 'X%'
where first_name = XXX order by last_name

これらのケースの多くでは、両方のインデックスが使用される可能性がありますが、1つが最適です。たとえば、次のクエリでidx_lfを検討します。

where first_name = XXX order by last_name

MySQLは、idx_lfを使用してテーブル全体を読み取り、order byの後にフィルタリングを実行できます。これは実際の最適化オプション(MySQLの場合)ではないと思いますが、他のデータベースでも発生する可能性があります。

14
Gordon Linoff

一般的なルールは、最も選択的なもの、つまり、結果が最も少ないものを最初に配置することです。したがって、たとえば10個の可能な値のstatus列とdateAdded列を含むテーブルに複数列のインデックスを作成している場合、通常は次のようなクエリを作成します。

SELECT * FROM myTable WHERE status='active' and dateAdded='2010-10-01'

...次に、最初にdateAddedを使用します。これにより、スキャンが行の10%(または「アクティブ」な割合)ではなく、数行に制限されるためです。

これにはかなりの考えと調整が必要です。ラーデンマキとリーチの本をチェックしてください。

5
Graham Charles