我們有一個由三個字段組成的複合主鍵(它在MySQL 5.1中)。在這個表上每秒鐘有近200個插入和200個選擇,並且表的大小約爲100萬行,並且正在增加。MySQL中的複合主鍵性能缺陷
我的問題是:「複合主鍵」是否會降低此表上插入和選擇的性能?
我應該使用簡單的自動增加INT ID字段而不是複合主鍵嗎? (我認爲答案是有很大關係的MySQL處理上多列索引的方式)
我們有一個由三個字段組成的複合主鍵(它在MySQL 5.1中)。在這個表上每秒鐘有近200個插入和200個選擇,並且表的大小約爲100萬行,並且正在增加。MySQL中的複合主鍵性能缺陷
我的問題是:「複合主鍵」是否會降低此表上插入和選擇的性能?
我應該使用簡單的自動增加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
,發動機將只需要查找在表本身的確切鍵值。
如果使用自動增量字段作爲假身份證:
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
,那麼發動機就需要,第一,查找索引ix_mytable_col1_col2
的(col1, col2)
值,從索引檢索該行指針(值爲id
),並在表格本身中通過id
進行另一次查找。
對於MyISAM
表,但這並沒有什麼區別,因爲MyISAM
表是堆組織的,行指針只是文件偏移量。
在這兩種情況下,都會創建相同的索引(對於PRIMARY KEY
或對於UNIQUE KEY
)並且將以相同的方式使用。
SELECT
的一小部分,儘管效果幾乎可以忽略不計,不值得擔心。INSERT
s,你肯定做足夠INSERT
s擔心它。如果它是一個MyISAM表,那麼INSERT
鎖定表,這比InnoDB表更重要。如果通過使用auto_increment主鍵,您可以將這些列保留爲未索引,那麼您將從該更改中受益。如果你仍然需要保留這三列的索引,但是(例如,如果你需要在它們的組合上強制實現唯一性),那麼它在性能方面不會做任何事情。如果是InnoDB,則組合主鍵將包含在每個二級索引中的每個條目中。
這意味着
這些當然分別是缺點和優點。
複合主鍵不一定是壞的,有時它們可以非常有幫助,因爲InnoDB將它們聚類在一起 - 這意味着使用少得多的IO操作就可以滿足對PK的(磁盤綁定)範圍掃描,非聚集索引。
當然,如果你在其他表中有外鍵,它們會更寬,並且它們需要包含主表中的整個鍵。
但我會說平衡,一般來說,不。擁有組合主鍵本身不會引起問題。然而,如果一個「大」的主鍵(例如大變量)超過聚類的優勢並且能夠使用覆蓋索引,那麼可以做到這一點。
這是否意味着如果我在'(reviewId,userId)'和'(userId)'上有一個二級索引的主鍵,這個索引將在內部包含'(userId,reviewId,userId)'? – Benjamin 2016-06-29 17:22:27
@Benjamin是的,你說得對。這裏清楚地陳述了http://dev.mysql.com/doc/refman/5.7/en/innodb-index-types.html和這本書http://shop.oreilly.com/product/0636920022343.do – 2016-11-02 09:04:06
+1。謝謝,非常好的解釋。 – Fr0zenFyr 2013-01-21 10:05:33