3つのフィールドで構成される複合主キーを持つテーブルがあります(これはMySQL 5.1にあります)。このテーブルには約200の挿入と毎秒200の選択があり、テーブルのサイズは約100万行であり、増加しています。
私の質問は次のとおりです。「複合主キー」は、このテーブルでの挿入と選択のパフォーマンスを低下させますか?
複合主キーの代わりに、単純な自動増加INT IDフィールドを使用する必要がありますか? (答えは、MySQLが複数の列のインデックスを処理する方法に非常に関連していると思います)
INSERT
とUPDATE
のパフォーマンスはほとんど変わりません。(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
の場合)、同じように使用されます。
InnoDBの場合、複合プライマリキーは各セカンダリインデックスの各エントリに含まれます。
この意味は
もちろん、これらはそれぞれ短所と長所です。
複合主キーは必ずしも悪いわけではありません。InnoDBがそれらをクラスター化するため、時には非常に役立つ場合があります。つまり、PKに対する(ディスク境界の)範囲スキャンは、より少ないIO非クラスター化インデックスでは必須です。
もちろん、他のテーブルに外部キーがある場合、それらはより広く、メインテーブルのキー全体を含める必要があります。
しかし、私は一般的に言って、通常はそうではありません。複合主キーがあっても、それ自体では問題は発生しません。ただし、「大きな」主キー(大きなvarcharsなど)があると、クラスタリングの利点とカバリングインデックスを使用できる利点を上回る場合があります。
SELECT
sの速度が少し低下しますが、その影響はほとんど無視でき、心配する価値はありません。INSERT
sの速度が低下し、心配するほどのINSERT
sを実行できます。これは、InnoDBテーブルの場合よりも、INSERT
がテーブルをロックするMyISAMテーブルの場合、はるかに懸念事項です。 auto_increment主キーを使用することにより、これらの列をインデックス付けしないでおくことができる場合は、変更によるメリットがあります。ただし、これらの3つの列にインデックスを付ける必要がある場合(たとえば、これらの列の組み合わせに一意性を適用する必要がある場合)は、パフォーマンスに関しては何もしません。