MySQL慢查询 - 使用Filesort

时间:2014-06-06 08:00:17

标签: mysql

我正在尝试在我的MySQL数据库上运行查询,这需要花费70多秒的时间来运行,而且我还在摸索为什么索引没有被使用。

以下是查询:

SELECT PriceId, InstrumentId, Date, Open, High, Low, Close, Volume, UnadjustedClose
FROM price
ORDER BY InstrumentId, Date DESC

价格表的索引包含InstrumentId,Date(以及其他索引)。该表本身有8000万行,由2个整数,一个日期,一个长整数和5个小数组成。

explain命令的类型为ALL,Null表示可能的键,键和ref,并告诉我系统正在使用filesort。

这是我从系统中获得的最好的吗?我希望使用索引来更快地进行排序。

添加了:

这里是表格定义:

PriceId int PK, NN, AI
InstrumentId int NN
Date Date NN
Open Decimal(12,4)
High Decimal(12,4)
Low Decimal(12,4)
Close Decimal(12,4)
UnadjustedClose Decimal(12,4)
Volume BigInt

Indexes:

Primary -> PriceId
IX_InstrumentId -> InstrumentId
IX_Date -> Date
IX_InstrumentDate -> InstrumentId, Date

解释输出是:

id: 1
select_type: Simple
table: price
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 77926335
Extra: using filesort

2 个答案:

答案 0 :(得分:1)

优化器不会使用索引,因为您正在检索所有行,并且索引不包含您尝试获取的所有列。这意味着,索引不是覆盖索引。

在大多数情况下,使用索引并根据索引查找记录以检索其他列而不是扫描整个表(当您检索所有内容时)时效率较低

你有一些选择:

  • 在索引中包含所有必需的列:这需要更多空间并减慢写入操作。
  • 根据索引中的第一列向查询添加过滤器。如果过滤器足够有选择性(将所需的行数缩减到合理的水平),服务器将使用您的索引。
  • 将数据过滤到合理的大小
  • 在应用程序中进行排序
  • 将主键(群集)修改为(InstrumentID ASC, Date DESC)

修改 有关最后一个选项的更多信息

您的表看起来像一个日志表。在日志表中,为每个记录添加唯一的整数ID以消除重复似乎是一种很好的做法(但在大多数情况下并非如此)。但是,在大多数情况下,您不使用该ID。在MySQL中,主键也是集群键(这意味着数据将按照磁盘上的顺序排序 - 或多或少,现在只是原谅碎片。)

在日志表中,最好使用记录实体的ID和时间戳(InstrumentID,在您的情况下为Date)作为聚簇索引(MySQL中的主键)。执行此操作时,数据的顺序将适合常见的业务需求,这意味着查询性能会更好。

如果InstrumentID和Date是唯一的(我认为它应该是,一个工具不能同时具有多个价格,并且在不到一秒的时间内改变价格真的很少),复合指数可能是更好。 (并添加一个比自动生成的整数值更好的分区表选项。)

附注:如果按照日期过滤或按日期排序,您可以更改PK中列的顺序。

END OF EDIT

您应该回答一些问题,以便找到更好的方法来实现目标:

  • 为什么需要从表中检索所有80M记录?
  • 您的应用程序是否真的使用了所有这些应用程序?
  • 如果是,是否可以在应用程序级别而不是数据库级别进行排序?
  • 记录的顺序真的算了吗?

答案 1 :(得分:0)

由于行数较多,您无法加快速度。从此查询创建Materialized View,一旦创建,访问速度就会更快。

MySQL不支持Materialized View,因此您可以使用教程here自行实现。