简体   繁体   English

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

[英]Optimizing MySql query (IN) to avoid using “Using filesort”

I need your help to optimize the query to avoid using "Using filesort". 我需要您的帮助来优化查询以避免使用“使用filesort”。 The query is: 查询是:

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

The Explain results: 解释结果:

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

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

SQL Fiddle http://sqlfiddle.com/#!2/50c4d/1/0 SQL Fiddle http://sqlfiddle.com/#!2/50c4d/1/0

Table: 表:

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;

Sample data: 样本数据:

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');

Index: 指数:

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

I'm always confused why people are so hell-bent on avoiding FILESORT !?! 我总是很困惑为什么人们如此FILESORT于避免使用FILESORT !?!

You are asking for a sub-set of a table based on the actor_id . 您要求基于actor_id的表的子集。 The server sees there is an index (PK or idx_test) on the actor_id field and will zip through the index to find the relevant records and return them. 服务器看到actor_id字段上有一个索引(PK或idx_test),并将压缩索引以查找相关记录并返回它们。 Now, additionally, you also want the output to be in a given order. 此外,此外,您还希望输出按给定顺序排列。 Had the order been ORDER BY actor_id then it would have been possible to make use of the fact that the fetched records were already pre-sorted on this field in the index (or PK). 如果订单是ORDER BY actor_id那么就可以利用已获取的记录已经在索引(或PK)中的此字段上预先排序的事实。 Thus, no re-sorting would be required and the output could be returned 'as-is' (**). 因此,不需要重新排序,输出可以“按原样”返回(**)。

BUT, you don't want them in order of actor_id , you want them in order of name . 但是,您不希望它们按照actor_id顺序排列,您希望它们按name顺序排列。 So, the machine does what you ask and sorts the records by name before returning them to you. 因此,机器会按照您的要求执行操作,并在返回给您之前按name对记录进行排序。 I doubt sorting such a small list is going to take up a lot of resources or time. 我怀疑排序如此小的清单会占用大量的资源或时间。

PS: I don't think the index helps you much here, in fact it (badly!) duplicates the (clustered) PK. PS:我不认为索引对你有多大帮助,实际上它(非常糟糕!)重复了(聚集的)PK。 The only (potential) benefit i can see for such an index would be that IF the actual table is much wider THEN it would work as a covering index for this query, reducing the I/O (++). 我可以看到这样一个索引的唯一(潜在)好处是,如果实际表格要宽得多,那么它将作为此查询的覆盖索引,减少I / O(++)。 Mind you, this also means you can't ask for any of the other fields when querying. 请注意,这也意味着您在查询时不能要求任何其他字段。

(**: I'm sure it's all a bit more complex internally) (**:我确信内部的内容有点复杂)

(++: Less I/O in case of SELECT , IUD will require more I/O) (++:在SELECT情况下I / O较少, IUD需要更多I / O)

You can use an index for the range predicate IN(...) . 您可以使用范围谓词 IN(...)的索引。 Or you can use an index to eliminate the filesort. 或者您可以使用索引来消除文件排序。

You can't get both operations to use an index , at least not when the column in the predicate is different from the column in the sort order. 您无法使这两个操作都使用索引 ,至少在谓词中的列与排序顺序中的列不同时也是如此。

You created this index: 您创建了此索引:

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

This helped to find the matching actor_id values. 这有助于找到匹配的actor_id值。 And the composite index included the name column you wanted. 复合索引包含您想要的name列。 But then you want it sorted by name . 但是你想要按name排序。 The index is not sorted by name , it's sorted by actor_id then by name . 索引不按name排序,按actor_id排序,然后按name排序。

Here's an Analogy to Explain Why This Doesn't Work: 这是一个类比来解释为什么这不起作用:

Suppose I ask you to look in the telephone book and find people whose last names are Franklin, Hamilton, Jefferson, Washington. 假设我要求你查看电话簿,找到姓氏为富兰克林,汉密尔顿,杰斐逊,华盛顿的人。 Then sort them by first name. 然后按名字排序。 The phone book is ordered by last name, then by first name. 电话簿按姓氏排序,然后按名字排序。 So you can find the last names quickly, but the first names are returned Benjamin, Alexander, Thomas, George -- not in any sensible order. 所以你可以快速找到姓氏,但是名字是由本杰明,亚历山大,托马斯,乔治归来的 - 没有任何明智的顺序。

To sort them by first name, you'd have to collect the results and then sort them manually. 要按名字对它们进行排序,您必须收集结果,然后手动对它们进行排序。 The fact that they were sorted in the telephone book doesn't help. 他们在电话簿中排序的事实没有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM