我需要您的帮助来优化查询以避免使用"使用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
=============================================== =============
表:
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
答案 0 :(得分:1)
我总是很困惑为什么人们如此痴迷于避免FILESORT
!?!
您要求基于actor_id
的表格子集。服务器看到actor_id
字段上有一个索引(PK或idx_test),它将压缩索引以查找相关记录并返回它们。此外,此外,您还希望输出按给定顺序排列。如果订单为ORDER BY actor_id
,那么就可以利用已获取的记录已在索引(或PK)中的此字段上预先排序的事实。因此,不需要重新排序,并且可以按原样返回输出。 (**)。
但是,您不希望它们按actor_id
的顺序排列,您希望它们按name
的顺序排列。因此,机器按照您的要求执行操作,并在将记录返回给您之前按name
对记录进行排序。我怀疑排序如此小的清单会占用大量的资源或时间。
(**:我确定它在内部都有点复杂)
(++:在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
排序。
这是一个类比来解释为什么这不起作用:
假设我要求你查看电话簿并找到那些人 姓氏是富兰克林,汉密尔顿,杰斐逊,华盛顿。然后排序 他们用名字。电话簿按姓氏排序,然后按姓氏排序 名字。所以你可以快速找到姓氏,但第一个 名字归还本杰明,亚历山大,托马斯,乔治 - 不在其中 明智的秩序。
要按名字对它们进行排序,您必须先收集结果 手动排序。他们在电话中排序的事实 本书没有帮助。