优化MySql查询(IN)以避免使用“使用filesort”

时间:2014-05-28 12:10:07

标签: mysql performance optimization query-optimization filesort

我需要您的帮助来优化查询以避免使用"使用filesort"。查询是:

SELECT name
FROM actor
WHERE actor_id IN (3333,1452,2587,3003,3044,3524,3700,7087,7088)
ORDER BY name ASC

解释结果:

1   SIMPLE  actor   range   PRIMARY PRIMARY 2       9   Using where; Using filesort

=============================================== =============

SQL小提琴 http://sqlfiddle.com/#!2/50c4d/1/0

表:

CREATE TABLE `actor` (
`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,  
PRIMARY KEY (`actor_id`),
UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB;

示例数据:

INSERT INTO `actor` VALUES (7087, 'Brill');
INSERT INTO `actor` VALUES (3333, 'Rey');
INSERT INTO `actor` VALUES (7088, 'Graves');
INSERT INTO `actor` VALUES (1452, 'Phoenix');
INSERT INTO `actor` VALUES (2587, 'Segal');
INSERT INTO `actor` VALUES (3003, 'Taylor');
INSERT INTO `actor` VALUES (3044, 'Daniels');
INSERT INTO `actor` VALUES (3524, 'Michaels');
INSERT INTO `actor` VALUES (3700, 'Tryme');

指数:

ADD INDEX idx_test (actor_id, name) -> EXTRA: Using where; Using index; Using filesort

2 个答案:

答案 0 :(得分:1)

我总是很困惑为什么人们如此痴迷于避免FILESORT!?!

您要求基于actor_id的表格子集。服务器看到actor_id字段上有一个索引(PK或idx_test),它将压缩索引以查找相关记录并返回它们。此外,此外,您还希望输出按给定顺序排列。如果订单为ORDER BY actor_id,那么就可以利用已获取的记录已在索引(或PK)中的此字段上预先排序的事实。因此,不需要重新排序,并且可以按原样返回输出。 (**)。

但是,您不希望它们按actor_id的顺序排列,您希望它们按name的顺序排列。因此,机器按照您的要求执行操作,并在将记录返回给您之前按name对记录进行排序。我怀疑排序如此小的清单会占用大量的资源或时间。

PS:我认为索引在这里对你没什么帮助,实际上它(非常糟糕!)重复了(聚集的)PK。我可以看到这样一个索引的唯一(潜在)好处是,如果实际表格要宽得多,那么它将作为此查询的覆盖索引,减少I / O(++)。请注意,这也意味着您在查询时无法询问任何其他字段。

(**:我确定它在内部都有点复杂)

(++:在SELECT的情况下减少I / O,IUD将需要更多I / O)

答案 1 :(得分:1)

您可以使用范围谓词 IN(...)的索引。或者您可以使用索引来消除文件排序。

您无法同时使用索引,至少在谓词中的列与排序顺序中的列不同时。

您创建了此索引:

ADD INDEX idx_test (actor_id, name) -> EXTRA: Using where; Using index; Using filesort

这有助于找到匹配的actor_id值。复合索引包含您想要的name列。但是你希望它按name排序。索引未按name排序,按actor_id排序,然后按name排序。

这是一个类比来解释为什么这不起作用:

  

假设我要求你查看电话簿并找到那些人   姓氏是富兰克林,汉密尔顿,杰斐逊,华盛顿。然后排序   他们用名字。电话簿按姓氏排序,然后按姓氏排序   名字。所以你可以快速找到姓氏,但第一个   名字归还本杰明,亚历山大,托马斯,乔治 - 不在其中   明智的秩序。

     

要按名字对它们进行排序,您必须先收集结果   手动排序。他们在电话中排序的事实   本书没有帮助。