SQL Query 总是按子句顺序使用文件排序

Posted

技术标签:

【中文标题】SQL Query 总是按子句顺序使用文件排序【英文标题】:SQL Query always uses filesort in order by clause 【发布时间】:2010-07-12 01:53:39 【问题描述】:

我正在尝试优化使用 order by 子句的 sql 查询。当我使用 EXPLAIN 时,查询总是显示“使用文件排序”。我将此查询应用于一个小组讨论论坛,其中用户的帖子附加了标签。

这是我使用的 3 个表:users、user_tag、tags

user_tag 是用户及其标签的关联映射表。

CREATE TABLE `usertable` (
 `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `user_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 PRIMARY KEY (`user_name`),
 KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `user_tag` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `user_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 `usage_count` int(11) unsigned NOT NULL,
 PRIMARY KEY (`id`),
 KEY `tag_id` (`tag_id`),
 KEY `usage_count` (`usage_count`),
 KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我使用编程更新了服务器端的usage_count。这是给我带来问题的查询。查询是找出特定用户名的tag_id和usage_count,按使用次数降序排序

select user_tag.tag_id, user_tag.usage_count
  from user_tag inner join usertable on usertable.user_id = user_tag.user_id
 where user_name="abc" order by usage_count DESC;

这里是解释输出:

mysql> explain select
    user_tag.tag_id,
    user_tag.usage_count from user_tag
    inner join usertable on
    user_tag.user_id = usertable.user_id
    where user_name="abc" order by
    user_tag.usage_count desc;

Explain output here

我应该改变什么来失去“使用文件排序”

【问题讨论】:

您实际上并没有显示 EXPLAIN 的输出。您可能还应该为每个表提供 SHOW CREATE TABLE 的输出。这将显示表上的索引。 @George - 我已经发布了 EXPLAIN 输出的链接。还编辑了问题以显示索引。 @OMG Ponies 我相信它们在大多数情况下都是同义词,如果不是全部的话。 @OMG Ponies - 当我输入 show indexes from user_tag 时,它会显示所有键 - usage_count、tag_id、user_id @George Marian:谢谢@ShiVik:这意味着它们是单独的索引 - 覆盖索引涉及多个列:mysqlperformanceblog.com/2006/11/23/… 【参考方案1】:

我对这个有点生疏了,但是就这样吧。

用于获取行的键与 ORDER BY 中使用的键不同:

http://dev.mysql.com/doc/refman/5.1/en/order-by-optimization.html

正如 OMG Ponies 所说,user_id、usage_count 上的索引可以解析文件排序。

KEY `user_id_usage_count` (`user_id`,`usage_count`)

【讨论】:

谢谢。我试过了,但这只是在解释的可能键列中添加了一个键。 explain 的 Extra 列保持不变。 在这种情况下用于获取行的键来自表“usertable”,而用于排序的键来自表“user_tag”。所以,基本上我不能创建一个同时具有这两个字段的键,对吧? @OMG Ponies - 我想你是对的。由于我的主表中的主字段和我的关联映射表中的外键不同,这就是我遇到问题的原因。我需要稍微调整一下我的表结构以使它们相同。【参考方案2】:

“使用文件排序”不一定是坏事;在许多情况下,这实际上并不重要。

此外,它的名称有些令人困惑。 filesort() 函数不一定使用临时文件来执行排序。对于小型数据集,数据在内存中排序非常快。

除非您认为这是一个特定问题(例如,在实验室对生产级硬件上的应用程序进行分析后,删除 ORDER BY 可以解决特定的性能问题),或者您的数据集很大,否则您可能不必担心关于它。

【讨论】:

以上是关于SQL Query 总是按子句顺序使用文件排序的主要内容,如果未能解决你的问题,请参考以下文章

如何按 Oracle SQL IN() 子句中的值顺序对结果数据进行排序

按查询的where子句中的字段顺序对sql查询的结果进行排序

Mysql中ORDER BY 排序怎么使用?指定顺序和多字段排列

SQL之SELECT语句排序

sql执行顺序

按子句顺序排列的 PL SQL CASE