我有许多表,其中有外键的索引,还有包含这些外键的聚集索引。例如,我有一个表,如下所示:
TABLE: Item
------------------------
id PRIMARY KEY
owner FOREIGN KEY
status
... many more columnsMySQL为主键和外键生成索引,但有时我希望提高查询性能,以便创建聚集索引或覆盖索引。这将导致具有重叠列的索引。
INDEXES ON: Item
------------------------
idx_owner (owner)
idx_owner_status (owner, status)如果我删除了idx_owner,以后通常使用idx_owner的查询只会使用idx_owner_status,因为它将owner作为索引中的第一列。
值得把idx_owner留在身边吗?是否有额外的I/O开销可以使用idx_owner_status,即使MySQL只使用部分索引?
编辑:我真正感兴趣的只是InnoDB对索引的行为方式。
发布于 2015-09-06 00:50:00
短答案删除较短的索引。
Long和Anwser要考虑的事情:
放下它:
INDEX都是驻留在磁盘上的一个单独的BTree,因此占用空间。INDEX在INSERT新行或UPDATE修改索引列时都会被更新(早晚)。这占用了一些CPU、I/O和buffer_pool空间,用于“变更缓冲区”。不要放弃:
INDEX(int, varchar255)。这是非常罕见的,最后一个项目真的超过其他项目。
奖金
“覆盖”索引是包含SELECT中提到的所有列的索引。例如:
SELECT status FROM tbl WHERE owner = 123;这将只触及BTree for 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)更多讨论在我的博客在http://mysql.rjweb.org/doc.php/index1和http://mysql.rjweb.org/doc.php/index_cookbook_mysql上。
https://stackoverflow.com/questions/32418812
复制相似问题