【问题标题】:order by causes filesort按原因排序
【发布时间】:2010-12-03 13:57:59
【问题描述】:

我还有以下问题

EXPLAIN EXTENDED SELECT
  `item`.`id`,
  `item`.`timestamp`,
  `item`.`label`
  FROM
  item
WHERE
  item.dataTypeId=30
GROUP BY
  item.id
ORDER BY
  item.timestamp DESC
LIMIT 0,6;

Id & timestamp 是主键对(mediumint+datetime) dataTypeId 是外键(mediumint) 表被创建为 InnoDb

可以有更多具有相同 id 和不同时间戳的记录(同一项目的版本)。这就是 group by 的原因

我读到了这个例子:similar topic on stackoverflow

但这并没有解决我的问题。

我尝试创建以下索引:

  1. (dataTypeId、id、时间戳)上的索引 - 按此顺序
  2. (dataTypeId,时间戳)上的索引 - 按此顺序
  3. id 上的索引
  4. 时间戳索引

最后两个有点绝望

我想我一定错过了一些基本的东西 -
但真的不知道是什么。
不要指望解决方案(这会很好:) 以正确的方式踢我 :)

sort_buffer_size 现在是 4194288

编辑: 解释 - 没有索引

"1" "SIMPLE"    "item"  "ref"   "FK_dataTypeId" "FK_dataTypeId" "4" "const" "5608"  "Using where; Using temporary; Using filesort"

解释创建的索引

"1" "SIMPLE"    "item"  "ref"   "FK_udssDataItem_1,testIndexType,testIndexTypeTimestamp,testIndexTypeIdTime"    "FK_udssDataItem_1" "4" "const" "5632"  "Using where; Using temporary; Using filesort"

【问题讨论】:

  • 文件排序不代表慢,请在EXPLAIN查询结果中抛出
  • 跨 5000 行的查询需要 2 秒,我已将原始查询简化为最小大小 - 并逐步尝试,除了一个又一个可能的原因。 EXPLAIN 中唯一的“热点”是带有“文件排序”的。另一行通过行数较少的索引进行操作...
  • 首先,您是按 id 分组,但您是按时间戳排序......这没有逻辑意义。您可能应该通过时间戳上的某个聚合函数 (AVG/MAX/MIN) 进行排序。
  • 是的,但是顺序列可能会有所不同 - 还有更多 - 发布日期时间、上次更新日期时间等。这只是一个示例。
  • 我的意思是 - 所有的列都是日期时间 - 我不确定是否 - 1)我有错误的索引,2)错误的配置

标签: mysql datetime innodb filesort


【解决方案1】:

您的查询存在问题。当您执行“按 id 分组”时,您可能对同一 id 有不同的时间戳,并且没有指定使用哪一个(Min()、max() 等)“标签”字段会出现类似的问题。

http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.html

因此您需要在时间戳和标签上使用聚合函数,否则返回的值可能无法预测。

由于您按 id 分组并按时间戳排序,因此 MySQL 为每个组提取一个时间戳,因此索引并没有太大帮助。您可能无法通过此查询摆脱文件排序。

【讨论】:

  • 天啊,当我看到我写的所有答案时,我真是太初学者了。我也不知道文件排序并不一定意味着慢。所以这就是为什么我首先怀疑这部分查询。感谢您的建议和链接文章。
【解决方案2】:

所以您的问题是“如何避免对查询进行文件排序”?
在这种情况下,要让 MySQL 进行索引排序,您需要在 where 子句中包含索引中的所有列。

使用 id,timestamp 主键你必须

where id = myid and item.timestamp between (t1,t2)

还要注意开放式范围(和时间戳

我不确定 datatypeID 是什么,但如果这是您唯一的条件,那么仅在该列上添加索引也应该建议进行索引排序。但您可能必须在 (timestamp,datatypeID) 上创建索引...以该顺序...代替。

【讨论】:

  • 正如@ajreal 提到的,文件排序并不总是坏的。我最近花了很多时间试图摆脱文件排序,但最终却几乎没有任何区别。如果您有多余的内存,一个简单的替代方法是将您的 /tmp 目录软链接到 /dev/shm,这样文件排序本质上就是一种内存排序。
  • 是的,这应该是我的问题。但是我仍然将所有列在 order 语句中放入索引中 - 仍然是文件排序。然后我将所有列放在 where 和 order 语句(文件排序)中。然后尝试其他组合(如我所写)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
  • 2012-03-16
相关资源
最近更新 更多