我有一个非常简单的查询:
SELECT comments.*
FROM comments
WHERE comments.imageid=46
这是我的表:
CREATE TABLE IF NOT EXISTS `comments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`imageid` int(10) unsigned NOT NULL DEFAULT '0',
`uid` bigint(20) unsigned NOT NULL DEFAULT '0',
`content` text CHARACTER SET utf8,
`adate` datetime DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ids` (`imageid`) USING BTREE,
KEY `dt` (`adate`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;
但是MySql不能在这个简单的查询中使用索引。这是解释结果:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE comments ALL ids NULL NULL NULL 4 75.00 Using where
当我将查询更改为此时,Mysql可以使用索引。为什么? :
SELECT comments.id
FROM comments
WHERE comments.imageid=46
这里是解释:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE comments ref ids ids 4 const 4 100.00 Using index
答案 0 :(得分:7)
我猜你在'comments'表中有几行,这就是为什么MySQL在你的第一个查询中进行全表扫描而不是使用索引的原因。它估计全表扫描的成本可能低于第一次匹配索引,然后查找行。
在第二个查询中使用索引,因为可以直接从索引获取查询的所有列('id'列),而不需要在匹配索引后查找表行。这是“使用索引”额外信息的含义。
如果在'comments'中有大量行,请尝试MySQL仍使用完整扫描,我认为这将是一种奇怪的行为。事实上,我在MySQL版本5.1中测试的完全相同,即使只有很少的行,它总是使用'索引'。
答案 1 :(得分:1)
您是否尝试过the standard sort of things?
答案 2 :(得分:1)
第二个查询是索引覆盖的查询。可以从索引中读取所请求的全部信息(因为主键是InnoDB中任何二级索引的一部分)。
在第一个查询中,MySQL必须从索引中读取PK,然后读取行。因为表具有如此少量的行,所以优化器决定如果直接读取行并丢弃那些不匹配的行会更快