2

我有一个具有这种结构的表(有 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 对其进行排序,所以我添加了 ( imageid, adate) 键。

但是这个查询的解释结果说 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
4

3 回答 3

1

没有正确阅读解释的结果。

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

如果 MySQL 不使用索引来解决问题,则说明中ORDER BY会有using filesort。在这两个查询中,ids都使用了键并且 MySQL执行表扫描

于 2012-04-15T14:24:02.493 回答
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 查询浏览器中检查执行时间。

于 2012-04-15T13:53:24.847 回答
0

直接出手册:

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

也许这适用于您的查询,因为您有一个组合KEY ids (imageid,adate)并且您没有imageidORDER BY. 您可以尝试为adateonly 添加一个密钥,看看是否有帮助。

于 2012-04-15T13:56:09.407 回答