为啥 MySQL 对此查询执行文件排序?

Posted

技术标签:

【中文标题】为啥 MySQL 对此查询执行文件排序?【英文标题】:Why is MySQL performing a filesort on this query?为什么 MySQL 对此查询执行文件排序? 【发布时间】:2017-12-10 19:36:30 【问题描述】:

为什么 mysql 对此查询执行文件排序?我只是期待Using where:

SELECT * FROM active_campaign_days
WHERE ad_unit_id=1
AND day='2017-12-10'
ORDER BY bid DESC, budget DESC, campaign_id ASC

(ad_unit_id, day, bid, budget, campaign_id) 上的索引 - 数据库根据 EXPLAIN 使用此索引。

在这个特定的结果集中,bidbudget 对于所有行都是相同的。 (ad_unit_id, campaign_id) 是独一无二的。

解释:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra   
1   SIMPLE  active_campaign_days    ref     ad_unit_id,ad_unit_id_2     ad_unit_id_2    7   const,const     5   Using where; Using filesort

【问题讨论】:

filesort 命名错误。任何时候无法从索引执行排序,它都是文件排序。它与文件无关。文件排序应该称为“排序”。它本质上是快速排序。 percona.com/blog/2009/03/05/… - 我花了大约 15 秒的时间来谷歌搜索。在添加问题之前,请花时间重新搜索 我知道什么是 mysql 文件排序。我在问为什么 MySQL 不能充分利用索引。如果您仔细阅读我的问题而不是草率下结论,您会看到我期待Using where,MySQL 表明它使用索引而不执行任何额外的排序。 @juergend - 感谢您的链接;我想知道我在哪里发现了 qsort 的提及。我多次说过“文件排序”并不像听起来那么邪恶。 【参考方案1】:

让我们剖析查询..

    WHERE ad_unit_id=1 AND day='2017-12-10' 需要一个以ad_unit_idday 开头的索引(以任意顺序)。这将提供最佳过滤。

    如果可行,可以将所有ORDER BY 添加到INDEX,这样就可以避免对数据进行排序。但是ORDER BY bid DESC, budget DESC, campaign_id ASC 存在问题。请注意,DESCASC 混合使用。 MySQL 只能在一个方向上扫描索引。这意味着所有必须是ASC 或所有必须是DESC。 (见下面的注释)所以,INDEX(ad_unit, day, bid, budget, campaign_id) 没有你想的那么有用。

    如果优化器可以通过第 2 步,然后在SELECT(即所有*)中添加提到的任何其他列任何地方,那么索引就会出现“覆盖”。这提供了不同种类的性能提升——通过在索引中完成所有工作,而不必触及“数据”。

注意:从版本 8.0 开始,MySQL 将在索引声明中使用DESC。因此,您可以说INDEX(ad_unit, day, bid DESC, budget DESC, campaign_id ASC),优化器可以在上面的第 2 项中使用它无需排序。 (在 8.0 之前,DESC 在索引声明中是允许的,但被忽略了。)

解决方法?它会改变输出的顺序,但您可能会接受所有列 ASC(或所有 DESC)?

与此同时,INDEX(ad_unit_id, day) 是所有值得拥有的东西。

【讨论】:

谢谢。在版本 8.0 之前,我不知道您不能以这种方式混合排序方向。我使用的是 5.6 版,所以很遗憾更新索引声明不是一个选项。但是,将所有排序设置为 DESC 确实消除了文件排序。我可能会更新我的后端,为最后一个排序键使用逆值。 @Dan - 你可以混合它们;你确实得到了想要的排序,但是没有索引会帮助你,并且会完成一个“排序”。除非性能差异足以引起关注,否则我不会将代码添加到后端。 (我怀疑这种伤害不会那么大。)

以上是关于为啥 MySQL 对此查询执行文件排序?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在这个非常简单的 MySQL 查询上得到文件排序?

MySQL 在执行“order by”时停留在“使用文件排序”上

mysql数据库多个表union all查询并排序的结果为啥错误

php执行sql查询,输出结果只有1条!?

linux下已经装了mysql,为啥mysql命令执行时报没有该命令

linux下已经装了mysql,为啥mysql命令执行时报没有该命令