2015-09-06 42 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