如果我选择多个列,Mysql EXPLAIN会显示'using filesort',但如果没有,则使用'using index'

时间:2013-04-24 21:06:52

标签: mysql sql

我有一个类似这样的表(我删除了很多字段以便于解释)。 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命令后看到了。可以做什么,所以它总是使用索引?我是否必须创建一个包含我选择的所有字段的索引?如果是,那么索引中字段的顺序是否重要?

2 个答案:

答案 0 :(得分:3)

如果选择索引未涵盖的列,则引擎必须进行表查找以获取这些列的值。

由于您仍在选择整个表格(不使用WHERELIMIT),因此顺序扫描表格然后对其进行排序比执行大量关键搜索更快。

此外,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列的索引),因为每个查询只使用一个索引。列将继续为骑行