我有一个包含约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
条件限制在特定年份或月份。
除了将年,月和日信息存储在单独的列中之外,有没有办法加快查询速度和/或避免临时表和文件输出?
答案 0 :(得分: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
列 - 使用触发器。