我可以在不存储 group by 和 order by value 的情况下加快此查询吗?
Posted
技术标签:
【中文标题】我可以在不存储 group by 和 order by value 的情况下加快此查询吗?【英文标题】:Can I speed this query up without storing the group by and order by value? 【发布时间】:2011-11-16 10:32:05 【问题描述】:我有以下疑问:
SELECT IF(dissolution_date IS NULL,
YEAR(CURDATE()) - YEAR(incorporation_date),
YEAR(dissolution_date) - YEAR(incorporation_date)) as length,
COUNT(DISTINCT(id_company)) as count
FROM company
WHERE incorporation_date IS NOT NULL
GROUP BY length
ORDER BY length ASC
鉴于我有解散日期(或替代日期)和成立日期,在表中添加一个额外的列来存储两个日期之间的差异似乎是多余的(特别是如果公司尚未解散,解散日期需要每 day 年更新一次)。
EXPLAIN 输出如下:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
----|-------------|---------|------|--------------------|------|---------|------|----------------------------------------
1 | SIMPLE | company | ALL | incorporation_date | NULL | NULL | NULL | 9128995 | Using where; Using filesort
目前查询需要 10 秒,而对非计算列的类似查询需要毫秒,这是我想在这里实现的。
是否可以在不使用文件排序且不将长度列添加到原始表的情况下按长度进行分组和排序?或者我应该只添加长度列,在这种情况下,每 day 年更新dissolution_date 的最佳方法是什么?
【问题讨论】:
用YEAR(COALESCE(dissolution_date, CURDATE())) - YEAR(incorporation_date) AS length
替换IF( ... )
怎么样
感谢您的提醒:COALESCE,但没有任何区别:(
COUNT(DISTINCT id_company)
有什么用? id_company
不是PK吗?如果是,您可以将其替换为 COUNT(*)
@ypercube 好喊,我不确定何时使用 DISTINCT COUNTS 以及何时使用 COUNT(*)
还有一件事。在 mysql 中,GROUP BY length ORDER BY length ASC
可以缩短为 GROUP BY length ASC
,保证相同的结果(通常性能更好)。您实际上也可以跳过ASC
,但我更喜欢它在那里向任何未来的代码阅读器识别查询应该做什么。
【参考方案1】:
您在数据库理论中所指的内容称为派生属性。您不想实现这样的属性,因为虽然它工作得很快,但它不是很准确。所以我们不会为这样的属性创建列,而是在需要时计算它。
文件不需要排序,order by子句就是这样做的。
假设您的查询是正确的,我建议使用搜索键属性(dissolution_date、incorporation_date)在公司表上创建一个 B 树索引,因为它们似乎在您的查询中被大量使用。
您能介绍一下公司表吗?
【讨论】:
但是,当我EXPLAIN
查询时,我得到了 Using where; Using index; Using temporary; Using filesort
...它确实使用了新密钥(长度为 4),但我想让它停止文件排序,如果可能
您能否进一步扩展“假设您的查询是正确的”?
为特定查询创建索引,因此:假设查询正确以上是关于我可以在不存储 group by 和 order by value 的情况下加快此查询吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 group by 中使用 datetime 日期并在单个 SELECT 中使用 order by 与使用子查询