我有一个这种结构的表(有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
答案 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)
在某些情况下,MySQL无法使用索引来解析ORDER BY,尽管它仍然使用索引来查找与WHERE子句匹配的行。这些情况包括:---您在密钥的非连续部分使用ORDER BY: SELECT * FROM t1 WHERE key2 = constant ORDER BY key_part2;
这可能适用于您的查询,因为您有一个复合KEY ids (imageid,adate)
而您在imageid
中没有使用ORDER BY
。您可以尝试仅为adate
添加密钥,看看是否有帮助。