2015-09-06 45 views
5

我有很多表,其中有外鍵的索引,以及包含這些外鍵的聚集索引。例如,我有類似下面的表格:複合索引的開銷

TABLE: Item 
------------------------ 
id  PRIMARY KEY 
owner FOREIGN KEY 
status 

... many more columns 

MySQL的生成主鍵和外鍵索引,但有時候,我想提高查詢性能,所以我會創建集羣或覆蓋索引。這導致具有重疊列的索引。

INDEXES ON: Item 
------------------------ 
idx_owner (owner) 
idx_owner_status (owner, status) 

如果我放棄idx_owner,通常會使用idx_owner只想用idx_owner_status因爲它owner作爲索引的第一列以後查詢。

是否值得保留idx_owner?即使MySQL僅使用索引的一部分,是否還有額外的I/O開銷來使用idx_owner_status

編輯:我真的只對InnoDB的行爲方式感興趣。

回答

5

簡短回答 刪除較短的索引。

龍Anwser 需要考慮的事情:

住嘴:

  • 每個INDEX是一個獨立的B樹駐留在磁盤上,因此它需要的空間。
  • 當您INSERT新行或UPDATE修改索引列時,每個INDEX都會更新(遲早)。這需要一些CPU和I/O以及'更改緩衝區'的buffer_pool空間。
  • 任何功能使用(與性能相反)較短的索引可以由較長的索引執行。

不要砸:

  • 較長的指數比較短的笨重。所以它不容易被緩存。所以(在極端情況下)使用較大的一個來代替較短的一個可能導致更多的I/O。一個加劇這種情況:INDEX(int, varchar255)

這是非常罕見的,最後一項真的覆蓋其他項目。

加成

A 「覆蓋」 指數是一個包含SELECT提到的所有列。例如:

SELECT status FROM tbl WHERE owner = 123; 

這將觸及 B樹的INDEX(owner, status),由此明顯快

SELECT status, foo FROM tbl WHERE owner = 123; 

如果你真的很需要那查詢要快,然後更換的你索引號爲INDEX(owner, status, foo)。在二次關鍵

PK

還有一個趣聞......在InnoDB中,該PRIMARY KEY的列隱含附加到每一個二級鑰匙。所以,這三個例子是真的

INDEX(owner, id) 
INDEX(owner, status, id) 
INDEX(owner, status, foo, id) 

在我的博客更多的討論composite indexesindex cookbook