如何避免这个mysql查询的文件排序

Posted

技术标签:

【中文标题】如何避免这个mysql查询的文件排序【英文标题】:How to avoid filesort for this mysql query 【发布时间】:2011-07-12 03:08:17 【问题描述】:

我需要一些帮助来避免对该查询进行文件排序。

  SELECT id 
    FROM articles USE INDEX(group)
   WHERE type = '4' 
     AND category = '161' 
     AND did < '10016' 
     AND id < '9869788' 
ORDER BY id DESC 
   LIMIT 10

INDEX(group) 是 (type, category, did, id) 的覆盖索引

由于ORDER BY id DESC,执行文件排序。有没有办法避免对此类查询进行文件排序?

【问题讨论】:

所有这些列的数据类型是数字(例如 int)吗?如果是这样,请从查询中的所有数字中删除引号。这将大大加快速度。 @Asaph:隐式转换可能没什么大不了的;我会删除单引号,因为它们给人的印象是错误的(假设列数据类型是数字) @OMG Ponies:你确定吗?即使对于这部分查询:did&lt;'10016' and id&lt;'9869788'?考虑排序数字和字符串是不同的。例如。 1 @Asaph:在可能的情况下,隐式转换由列数据类型决定。如果did 是数字,您会不会期望与字符串进行比较时出错? ;) @OMG Ponies:我在 mysql 中进行了一些测试,并证实了您所说的。固执地,我认为选择将字符串转换为整数(可能有损)而不是将整数转换为字符串(非有损)在逻辑纯粹主义者的意义上是完全错误的。但从实际的角度来看,将字符串转换为整数几乎总是用户想要的。所以我认为这个选择是合理的。 @Vern:感谢您试用。无论如何,您都应该删除引号,即使性能没有提高。 【参考方案1】:

更改索引列顺序。该索引对排序没有用处,因为它是第 4 列,还不能按原样使用。

当然,这会影响索引对这个 WHERE 的有用性,因为在相等列之前需要一个不等列

在MySQL docs 中,您破坏了“您在键的非连续部分上使用 ORDER BY”和“用于获取行的键与 ORDER BY 中使用的键不同”

编辑:根据我上面的链接,您不能拥有同时满足 WHERE 和 ORDER BY 的索引。由于我在上面发布的两个条件,它们是互斥的

另一个建议:

id 上的单列索引 也回到原来的索引 移除索引提示 希望优化器解决两个索引都可以使用(“索引交集”)

【讨论】:

那么你建议什么顺序?也许(id、did、type、category)? @Vern:最常用的列在左侧,第二常用的列在第二位,依此类推。 @OMG Ponies:具体到这个查询,什么顺序会避免文件排序? Id 在前,因此它与排序匹配。 @Vern:天哪。再说一遍:id 不应该是第一个。请仔细阅读该链接。尤其是第二个例子,关于 key_parts【参考方案2】:

在 id 上创建索引并键入它应该适合您。 如果 Id 是唯一的,您还可以为其创建主键。

您的查询正在使用文件排序,因为优化器可能正在使用您在查询中创建的索引的第一列。

【讨论】:

以上是关于如何避免这个mysql查询的文件排序的主要内容,如果未能解决你的问题,请参考以下文章

MySQL避免内部查询中的文件排序

MySQL - 加速查询避免文件排序和临时

在 MySQL 查询中使用 OR 时,有没有办法使用索引来避免文件排序?

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

如何优化这个 MySQL 查询

mysql 如何 多表连查 按时间到排序