web-dev-qa-db-ja.com

MySQLの複合主キーパフォーマンスの欠点

3つのフィールドで構成される複合主キーを持つテーブルがあります(これはMySQL 5.1にあります)。このテーブルには約200の挿入と毎秒200の選択があり、テーブルのサイズは約100万行であり、増加しています。

私の質問は次のとおりです。「複合主キー」は、このテーブルでの挿入と選択のパフォーマンスを低下させますか?

複合主キーの代わりに、単純な自動増加INT IDフィールドを使用する必要がありますか? (答えは、MySQLが複数の列のインデックスを処理する方法に非常に関連していると思います)

43
Ahmad

INSERTUPDATEのパフォーマンスはほとんど変わりません。(INT)キーと(INT, INT)キーのパフォーマンスはほとんど同じです。

SELECTコンポジットのパフォーマンスPRIMARY KEYは多くの要因に依存します。

テーブルがInnoDBの場合、テーブルはPRIMARY KEY値に暗黙的にクラスター化されます。

つまり、両方の値がキーを構成している場合、両方の値の検索が高速になります。追加のキー検索は必要ありません。

クエリが次のようなものであると想定します。

SELECT  *
FROM    mytable
WHERE   col1 = @value1
        AND col2 = @value2

そしてテーブルレイアウトはこれです:

CREATE TABLE mytable (
        col1 INT NOT NULL,
        col2 INT NOT NULL,
        data VARCHAR(200) NOT NULL,
        PRIMARY KEY pk_mytable (col1, col2)
) ENGINE=InnoDB

、エンジンはテーブル自体の正確なキー値を検索する必要があるだけです。

自動インクリメントフィールドを偽のIDとして使用する場合:

CREATE TABLE mytable (
        id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        col1 INT NOT NULL,
        col2 INT NOT NULL,
        data VARCHAR(200) NOT NULL,
        UNIQUE KEY ix_mytable_col1_col2 (col1, col2)
) ENGINE=InnoDB

、次に、エンジンはまず、インデックス(col1, col2)内のix_mytable_col1_col2の値を検索し、インデックスから行ポインタを取得して(idの値)、別の検索を行う必要があります。テーブル自体のidによって。

ただし、MyISAMテーブルの場合、これは違いがありません。MyISAMテーブルはヒープ構成であり、行ポインターは単なるファイルオフセットであるためです。

どちらの場合も、同じインデックスが作成され(PRIMARY KEYまたはUNIQUE KEYの場合)、同じように使用されます。

55
Quassnoi

InnoDBの場合、複合プライマリキーは各セカンダリインデックスの各エントリに含まれます。

この意味は

  • セカンダリインデックスは、これらの列+主キーのすべての列と同じだけのスペースを使用します
  • 必要なすべての列がセカンダリインデックス+ pkに含まれている場合、セカンダリインデックスをカバーインデックスとして使用できます。

もちろん、これらはそれぞれ短所と長所です。

複合主キーは必ずしも悪いわけではありません。InnoDBがそれらをクラスター化するため、時には非常に役立つ場合があります。つまり、PKに対する(ディスク境界の)範囲スキャンは、より少ないIO非クラスター化インデックスでは必須です。

もちろん、他のテーブルに外部キーがある場合、それらはより広く、メインテーブルのキー全体を含める必要があります。

しかし、私は一般的に言って、通常はそうではありません。複合主キーがあっても、それ自体では問題は発生しません。ただし、「大きな」主キー(大きなvarcharsなど)があると、クラスタリングの利点とカバリングインデックスを使用できる利点を上回る場合があります。

22
MarkR
  1. その複合主キーがあると、SELECTsの速度が少し低下しますが、その影響はほとんど無視でき、心配する価値はありません。
  2. これらの列にインデックスを付けるとまったくになり、INSERTsの速度が低下し、心配するほどのINSERTsを実行できます。これは、InnoDBテーブルの場合よりも、INSERTがテーブルをロックするMyISAMテーブルの場合、はるかに懸念事項です。 auto_increment主キーを使用することにより、これらの列をインデックス付けしないでおくことができる場合は、変更によるメリットがあります。ただし、これらの3つの列にインデックスを付ける必要がある場合(たとえば、これらの列の組み合わせに一意性を適用する必要がある場合)は、パフォーマンスに関しては何もしません。
3
chaos