【问题标题】:Why I can't get rid of filesort in a MySQL query that I already build index for为什么我无法在我已经为其构建索引的 MySQL 查询中摆脱文件排序
【发布时间】:2013-10-25 08:50:42
【问题描述】:

我有一个具有以下架构的表

Id、INT、主键

QueryId,INT

创建时间,日期时间

我创建了复合 index(QueryId, CreatedTime)

我跑的时候怎么会这样 解释 select * from test where queryid in (1,6) order by createdtime desc

我仍然得到以下具有文件排序的内容?任何想法我怎么能删除文件排序? “使用 where;使用文件排序”

【问题讨论】:

  • MySQL 的优化器已确定对文件进行排序比遍历 此查询 的索引要快。如果查询不同,或者表中的行数不同,MySQL 可能会选择做其他事情。让它发挥作用——它几乎肯定比你我更擅长。

标签: mysql indexing range filesort


【解决方案1】:

您实际上还没有构建可用于该查询的索引。

索引只能用于从最左列向右进行查找和排序。一旦遇到无用的东西,索引的其余部分就会被忽略。

您没有发布 EXPLAIN 的输出,但我怀疑如果正在检查索引并且 QueryId 是 INT,您会发现 Key_len = 4 意味着只有最左边的 4 个字节(QueryId) 对优化器很有用。

当且仅当您为 QueryId 选择 single 值时,(QueryId,CreatedTime)上的索引用于按 QueryId 提取记录,并按 CreatedTime 对它们进行排序。当您这样做时,索引将返回与该 QueryId 匹配的行,这些行已经按 CreatedTime 排序,并且优化器会意识到这一点。

相反,如果您查找 QueryId 的多个值,则索引返回的行在每组 QueryId 中按 QueryId 和 然后 按 CreatedTime 排序返回...因此需要进一步的文件排序因为 CreatedTime 值基本上没有按有用的顺序排序。如果你ORDER BYQueryId, CreatedTime,文件排序当然应该消失,但这可能不是你想要的。

(CreatedTime,QueryId) 上的索引也无济于事,因为 QueryId 不在左侧,除非行数非常少,否则服务器可以提取由 CreatedTime 预先排序的行,但它必须扫描所有行才能找到 QueryId 的匹配值。

简而言之,您不能完全为这样的查询编制索引,而且Using filesort 也并非总是可以避免的。

【讨论】:

  • 嗨迈克尔,我在原始问题中添加了解释结果图像,请看一下。我在网上找了几个地方和我一样的情况,他们用的方法和我一样,声称生效
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-25
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多