8

我有一个非常简单的查询:

  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 可以使用 index. 为什么?:

  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
4

3 回答 3

8

我猜你的“comments”表中的行数很少,这就是 MySQL 进行全表扫描而不是在第一个查询中使用索引的原因。据估计,全表扫描的成本可能低于首先匹配索引然后查找行的成本。

在您的第二个查询中使用索引,因为可以直接从索引中获取查询的所有列(“id”列),而无需在匹配索引后查找表行。这就是“使用索引”额外信息的含义。

尝试如果“评论”中的大量行 MySQL 仍然使用完整扫描,我认为这将是一种奇怪的行为。事实上,我在 MySQL 5.1 版本中进行了完全相同的测试,即使行数很少,它也总是使用“索引”。

于 2012-04-15T09:42:45.210 回答
1

你试过标准 的东西吗?

于 2012-04-15T08:54:17.333 回答
1

第二个查询是索引覆盖查询。请求的全部信息可以从索引中读取(因为主键是 InnoDB 中任何二级索引的一部分)。

在第一个查询中,MySQL 必须从索引中读取 PK,然后读取行。因为表的行数太少,优化器决定直接读取行并丢弃不匹配的行会更快

于 2012-04-15T11:06:47.327 回答