MySql没有使用带ORDER BY的索引

时间:2012-04-15 13:30:14

标签: mysql indexing sql-order-by

我有一个这种结构的表(有50k字段):

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`,`adate`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=52236 ;

我想通过imageid选择数据并使用adate对其进行排序,因此我添加了(imageidadate)键。

但是这个查询的解释结果说MuSQL仍然使用表扫描。为什么呢?!

EXPLAIN SELECT   comments.*
FROM comments
WHERE comments.imageid=50
ORDER BY
comments.adate DESC LIMIT 10

结果:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  comments    ref     ids     ids     4   const   203     Using where

并使用此索引:

KEY `ids` (`imageid`,`adate`,`id`) USING BTREE

此查询的结果:

EXPLAIN SELECT   comments.id
FROM comments
WHERE comments.imageid=50
ORDER BY
comments.adate DESC LIMIT 10

时:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  comments    ref     ids     ids     4   const   203     Using where; Using index

3 个答案:

答案 0 :(得分:1)

正确阅读解释结果。

using index表示查询是索引覆盖的 - 数据仅从索引读取,并且不使用实际行。这不是因为索引不同,而是因为在第二个查询中您只选择了id。

如果MySQL不使用索引来解析ORDER BY,那么解释中会有using filesort。在两个查询中,使用ids密钥,MySQL perofrm表扫描

答案 1 :(得分:0)

对于InnoDB,创建一个这样的键(imageid,adate,id);索引中列的顺序很重要。

然后试试这个 -

EXPLAIN SELECT   comments.id
FROM comments
WHERE comments.imageid=50
ORDER BY
comments.adate DESC LIMIT 10

让我知道输出是什么。

感谢您的输出。 添加以下部分。

如果您需要的内容超过了ID,请尝试使用此类内容

EXPLAIN 
SELECT c1.* from comments as c1
JOIN
(
   SELECT comments.id
   FROM comments
   WHERE comments.imageid=50
   ORDER BY
   comments.adate DESC LIMIT 10
) as c2 ON (c1.id=c2.id)

但这次不依赖于Explain。解释仍将显示带索引的一行。而是在phpmyadmin或mysql查询浏览器中检查执行时间。

答案 2 :(得分:0)

Straight out of the manual:

  

在某些情况下,MySQL无法使用索引来解析ORDER BY,尽管它仍然使用索引来查找与WHERE子句匹配的行。这些情况包括:---您在密钥的非连续部分使用ORDER BY:   SELECT * FROM t1 WHERE key2 = constant ORDER BY key_part2;

这可能适用于您的查询,因为您有一个复合KEY ids (imageid,adate)而您在imageid中没有使用ORDER BY。您可以尝试仅为adate添加密钥,看看是否有帮助。