【问题标题】:MySQL uses filesort on indexed TIMESTAMP columnMySQL 在索引的 TIMESTAMP 列上使用文件排序
【发布时间】:2012-10-15 08:07:42
【问题描述】:

我有一个拒绝使用索引的表,它总是使用文件排序。

表格是:

创建表`文章`( `ID` int(11) NOT NULL AUTO_INCREMENT, `Category_ID` int(11) 默认 NULL, `子类别` int(11) 默认为空, `CTimestamp` 时间戳 NOT NULL DEFAULT CURRENT_TIMESTAMP, `Publish` tinyint(4) 默认为空, `Administrator_ID` int(11) 默认为 NULL, `位置` tinyint(4)默认'0', 主键(`ID`), KEY `Subcategory` (`Subcategory`,`Position`,`CTimestamp`,`Publish`), KEY `Category_ID` (`Category_ID`,`CTimestamp`,`Publish`), KEY `Position` (`Position`,`Category_ID`,`Publish`), KEY `CTimestamp` (`CTimestamp`), 约束`article_ibfk_1`外键(`Category_ID`)参考`category`(`ID`) ) 引擎=InnoDB AUTO_INCREMENT=94290 默认字符集=utf8

查询是:

SELECT * FROM article ORDER BY `CTimestamp`;

解释是:

+----+-------------+---------+------+------------- --+------+----------+------+-------+--------------- -+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+---------+------+------------- --+------+----------+------+-------+--------------- -+ | 1 |简单 |文章 |全部 |空 |空 |空 |空 | 63568 |使用文件排序 | +----+-------------+---------+------+------------- --+------+----------+------+-------+--------------- -+

当我删除“ORDER BY”时,一切正常。所有其他索引(子类别、位置等)在其他查询中运行良好。不幸的是,即使使用我的简单选择查询,也拒绝使用时间戳。我确定我在这里遗漏了一些重要的东西。

如何让 MySQL 使用时间戳索引?

谢谢。

【问题讨论】:

  • 当您尝试创建索引并放置您尝试创建索引的代码时遇到什么错误(在我的网络 ajax 被阻止我无法评论那里这就是我问的原因在这里)。

标签: mysql timestamp indexing


【解决方案1】:

在这种情况下,MySQL 没有使用您的索引进行排序,这是一件好事。 为什么?您的表仅包含 64k 行,平均行宽约为 26 字节(如果我添加了正确的列大小),因此磁盘上的总表大小应约为 2MB。 只需将 2MB 的数据从磁盘读取到内存中(可能只需 1-2 次磁盘操作或搜索),然后简单地在内存中执行文件排序(可能是快速排序的变体),这是非常便宜的。

如果 MySQL 按索引顺序进行检索,它必须执行 64000 次磁盘查找操作,一条又一条记录!它会非常非常慢。

当您可以使用索引快速跳转到大文件中的已知位置并仅读取少量数据时,索引可能会很好,例如在 WHERE 子句中。但是,在这种情况下,这不是一个好主意——而且 MySQL 并不愚蠢!

如果您的表非常大(超过 RAM 大小),那么 MySQL 肯定会开始使用您的索引 - 这也是一件好事。

【讨论】:

  • 所以Using filesort 实际上意味着它是在在内存中完成的?非常混乱的名字。
  • 是的,它是在大小为@@sort_buffer_size 的缓冲区中完成的(在我的盒子上是16MB)
  • 谢谢。那么如何报告 on disk 排序? (如果sort_buffer_size小于要排序的结果)
  • 我想你看不出来。本文深入解释了这个过程s.petrunia.net/blog/?p=24
【解决方案2】:

嗯,你总是可以提示索引。将您的查询更改为

SELECT * FROM article use index (CTimestamp);

这会强制 MySQL 使用索引进行查询。解释:

1, 'SIMPLE', 'article', 'ALL', '', '', '', '', 1, 100.00, ''

看不到文件排序,因为使用的索引是 CTimestamp,所以应该对结果进行相应的排序。

或者,您可以保留 order by 子句,但强制使用索引:

SELECT * FROM article force index (CTimestamp) order by CTimestamp;

不过,问题仍然很奇怪。您是否考虑将其发布到官方 MySQL 帮助论坛?

编辑:你似乎是in good company
编辑:强制索引seems to work out well

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2011-09-01
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 2014-01-12
    • 2012-11-11
    相关资源
    最近更新 更多