我有一个类似这样的表(我删除了很多字段以便于解释)。 orderId是一个int非唯一值,用于显示行的重要程度(并在返回数据时按顺序排序)
CREATE TABLE `my_images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`orderId` int(11) NOT NULL,
`slug` varchar(50) NOT NULL,
`imageFilename` varchar(255) NOT NULL,
`thumb200` varchar(255) NOT NULL,
`thumb600` varchar(255) NOT NULL,
`md5hash` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `orderId` (`orderId`),
KEY `thumb600` (`thumb600`),
KEY `slug` (`slug`),
KEY `multiple_1` (`md5hash`,`orderId`,`thumb200`,`thumb600`),
KEY `md5hash` (`md5hash`),
KEY `thumb200` (`thumb200`),
KEY `thumb200_2` (`thumb200`,`orderId`),
KEY `orderId_2` (`orderId`,`thumb600`,`thumb200`),
KEY `thumb600_2` (`thumb600`,`orderId`),
KEY `thumb600_3` (`thumb600`,`orderId`),
KEY `orderId_3` (`orderId`,`thumb600`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
是的 - 有很多索引覆盖orderId。它是针对修复当前问题的尝试,也是我在WHERE语句中使用这些字段的混合。
无论如何,如果我运行此命令:
explain SELECT id FROM my_images
ORDER BY orderId asc
它输出(“使用索引”)
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE my_images index NULL orderId 4 NULL 174553 Using index
是预期的 - orderId是一个索引。
但如果我这样做:
explain SELECT id, thumb600, imageFilename, slug FROM my_images
ORDER BY orderId asc
它输出(使用filesort):
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE my_images ALL NULL NULL NULL NULL 174553 Using filesort
奇怪的是,如果我这样做
explain SELECT id, md5hash FROM my_images
ORDER BY orderId asc
它说“使用索引;使用filesort”
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE my_images index NULL multiple_1 775 NULL 174553 Using index; Using filesort
我注意到的原因是因为我看到了一个缓慢的查询,它基本上是'按顺序选择(一堆字段)按顺序限制4000,3',这需要很长时间,并且在运行explain命令后看到了。可以做什么,所以它总是使用索引?我是否必须创建一个包含我选择的所有字段的索引?如果是,那么索引中字段的顺序是否重要?
答案 0 :(得分:3)
如果选择索引未涵盖的列,则引擎必须进行表查找以获取这些列的值。
由于您仍在选择整个表格(不使用WHERE
或LIMIT
),因此顺序扫描表格然后对其进行排序比执行大量关键搜索更快。
此外,MySQL
无法进行后期行查找,这意味着它在计算偏移量之前总是查找表,即使使用索引也是如此。
如果您要通过InnoDB
表中的非PK字段进行排序,请尝试以下操作:
SELECT i.*
FROM (
SELECT id
FROM my_images
ORDER BY
orderId
LIMIT 4000, 3
) q
JOIN my_images i
ON i.id = q.id
在我的博客中查看此文章以获得解释:
答案 1 :(得分:2)
添加索引订单ID,然后添加您想要的列作为索引
问题是当你添加其他列时,filesort就像粘滞便笺一样,它必须重新收集它们
但是如果索引中有列(它必须是一个包含4-6列的索引),因为每个查询只使用一个索引。列将继续为骑行