我有以下查询,有点贵(目前为500毫秒):
SELECT * FROM events AS e, event_dates AS ed
WHERE e.id=ed.event_id AND ed.start >= DATE(NOW())
GROUP BY e.modified_datetime, e.id
ORDER BY e.modified_datetime DESC,e.created_datetime DESC
LIMIT 0,4
我一直在努力想出如何加快速度,并注意到将ed.start >= DATE(NOW())
更改为ed.start = DATE(NOW())
会在20ms内运行查询。任何人都可以帮助我加快这个日期比较的方法吗?在运行查询之前计算DATE(NOW())会有帮助吗?
编辑:这有帮助,使用EXPLAIN语句
BEFORE
table=event_dates
type=range
rows=25962
ref=null
extra=using where; Using temporary; Using filesort
AFTER
table=event_dates
type=ref
rows=211
ref=const
extra=Using temporary; Using filesort
答案 0 :(得分:2)
SELECT * FROM events AS e
INNER JOIN event_dates AS ed ON (e.id=ed.event_id)
WHERE ed.start >= DATE(NOW())
GROUP BY e.modified_datetime, e.id
ORDER BY e.modified_datetime DESC,e.created_datetime DESC
LIMIT 0,4
备注
select *
(另一种反模式),明确说明您需要的字段。 REPAIR TABLE tablename
。group by -e.modified_datetime, e.id
以最小化order by
子句所需的重新排序。 (不确定这一点,想知道结果) 答案 1 :(得分:2)
作为参考,使用,
表示连接是不好的做法,并且导致执行计划不佳。
SELECT
*
FROM
events AS e
INNER JOIN
event_dates AS ed
ON e.id=ed.event_id
WHERE
ed.start >= DATE(NOW())
GROUP BY
e.modified_datetime,
e.id
ORDER BY
e.modified_datetime DESC,
e.created_datetime DESC
LIMIT 0,4
为什么=
比>=
更快只是因为>=
是Range
的值,而不是非常具体的值。这就像是说“从第101页开始,让我从书中获取页面”而不是“让我第101页”。根据定义,它更加密集,特别是当您的查询涉及聚合和排序更多记录时。
在优化方面,您最好的选择是确保相关索引......
event_dates:
- start
上的索引应该足够了
事件:
- id
上的索引将显着改善联接效果
- 将modified_datetime
和created_datetime
添加到该索引可能会有所帮助
答案 2 :(得分:2)
您正在分组和搜索的字段可能缺少索引。请向我们提供:SHOW INDEXES FROM events
和SHOW INDEXES FROM event_dates
如果没有索引,则可以添加它们:
ALTER TABLE events ADD INDEX(modified_datetime);
ALTER TABLE events ADD INDEX(created_datetime);
ALTER TABLE event_dates ADD INDEX(start);
ALTER TABLE events ADD INDEX(modified_datetime);
ALTER TABLE events ADD INDEX(created_datetime);
ALTER TABLE event_dates ADD INDEX(start);
还要确保在字段中显示它们。但在这里你可能希望将它们作为主键。
答案 3 :(得分:1)
提前计算DATE(NOW())
不会对性能产生任何影响。它只计算一次(不是每行)。但是您有2个不同的查询(一个使用>=
,另一个使用=
)。看起来很自然,第一个(>=
)需要更长的时间来执行,因为它返回了更多的行。此外,与使用=
的查询相比,它可能决定使用不同的执行计划,例如,全表扫描而不是索引搜索/扫描
答案 4 :(得分:0)
你可以做这样的事情
DECLARE @CURRENTDATE AS DATETIME
SET @CURRENTDATE = GETDATE()
然后更改您的代码以使用
@CURRENTDATE variable.... "e.start >= @CURRENTDATE