0

我有一个包含约 1000 万个条目的数据库,每个条目都包含一个存储为DATE的日期。

我已经使用非唯一的 BTREE 对该列进行了索引。

我正在运行一个查询,计算每个不同年份的条目数:

SELECT DISTINCT(YEAR(awesome_date)) as year, COUNT(id) as count
FROM all_entries
WHERE awesome_date IS NOT NULL
GROUP BY YEAR(awesome_date)
ORDER BY year DESC;

该查询目前运行大约需要 90 秒,EXPLAIN 输出说明了原因:

id | select_type | table        | type  | possible_keys | key | key_len | ref | rows     | Extra
----------------------------------------------------------------------------------------------------------------------------------------
1  | SIMPLE      | all_entries  | ALL   | awesome_date  |     |         |     | 9759848  |  Using where; Using temporary; Using filesort

如果我FORCE KEY(awesome_date)将行数减少到 ~800 万并且key_len = 4, 但仍然是Using where; Using temporary; Using filesort.

我还运行查询,选择DISTINCT(MONTH(awesome_date))并使用将它们限制在特定年份或月份DISTINCT(DAY(awesome_date))的相关条件。WHERE

除了将年、月和日信息存储在单独的列中之外,有没有一种方法可以加快查询速度和/或避免临时表和文件排序?

4

1 回答 1

1

如果不将日期拆分为 3 列,您可以:

  • 首先,你应该删除 DISTINCT,它是没用的。– ypercube 1 分钟前 编辑

  • 去掉ORDER BY year,这将有助于提高速度(有点)。更改Group By为:(GROUP BY YEAR(awesome_date) DESC这仅适用于 MySQL 方言)。

  • 更改COUNT(id)COUNT(*)(假设id永远不会NULL,这在许多 MySQL 版本中更快)。

总之,查询将变为:

SELECT YEAR(awesome_date) AS year
     , COUNT(*) AS cnt              --- not good practise to use reserved words
                                    --- for aliases
FROM all_entries
WHERE awesome_date IS NOT NULL
GROUP BY YEAR(awesome_date) DESC ;

更好(更快)的解决方案是:

  • 您将列拆分为 3(年、月、日)的建议

  • 从 MySQL 更改为 MariaDB(即 MySQL 分支)并使用VIRTUAL PERISTENT该年的列,并在该虚拟列上添加索引。

  • 留在 MySQL 中并year自己添加一个持久列 - 通过使用触发器。

于 2012-04-24T12:24:31.017 回答