2009-09-22 46 views
40

我們有一個由三個字段組成的複合主鍵(它在MySQL 5.1中)。在這個表上每秒鐘有近200個插入和200個選擇,並且表的大小約爲100萬行,並且正在增加。MySQL中的複合主鍵性能缺陷

我的問題是:「複合主鍵」是否會降低此表上插入和選擇的性能?

我應該使用簡單的自動增加INT ID字段而不是複合主鍵嗎? (我認爲答案是有很大關係的MySQL處理上多列索引的方式)

回答

50

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 

,發動機將只需要查找在表本身的確切鍵值。

如果使用自動增量字段作爲假身份證:

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)並且將以相同的方式使用。

+0

+1。謝謝,非常好的解釋。 – Fr0zenFyr 2013-01-21 10:05:33

2
  1. 讓這個組合主鍵減慢SELECT的一小部分,儘管效果幾乎可以忽略不計,不值得擔心。
  2. 這些列索引在所有減慢您的INSERT s,你肯定做足夠INSERT s擔心它。如果它是一個MyISAM表,那麼INSERT鎖定表,這比InnoDB表更重要。如果通過使用auto_increment主鍵,您可以將這些列保留爲未索引,那麼您將從該更改中受益。如果你仍然需要保留這三列的索引,但是(例如,如果你需要在它們的組合上強制實現唯一性),那麼它在性能方面不會做任何事情。
22

如果是InnoDB,則組合主鍵將包含在每個二級索引中的每個條目中。

這意味着

  • 你的二級指標將採取儘可能多的空間,這些列+的所有列在主鍵
  • 您可以使用輔助索引作爲覆蓋索引,如果所有的列要求包含在二級指標中+ pk

這些當然分別是缺點和優點。

複合主鍵不一定是壞的,有時它們可​​以非常有幫助,因爲InnoDB將它們聚類在一起 - 這意味着使用少得多的IO操作就可以滿足對PK的(磁盤綁定)範圍掃描,非聚集索引。

當然,如果你在其他表中有外鍵,它們會更寬,並且它們需要包含主表中的整個鍵。

但我會說平衡,一般來說,不。擁有組合主鍵本身不會引起問題。然而,如果一個「大」的主鍵(例如大變量)超過聚類的優勢並且能夠使用覆蓋索引,那麼可以做到這一點。

+0

這是否意味着如果我在'(reviewId,userId)'和'(userId)'上有一個二級索引的主鍵,這個索引將在內部包含'(userId,reviewId,userId)'? – Benjamin 2016-06-29 17:22:27

+0

@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