我有MariaDB 10.1.14,很长一段时间我没有遇到任何问题(大约花了3秒钟)进行以下查询:
SELECT
sum(transaction_total) as sum_total,
count(*) as count_all,
transaction_currency
FROM
transactions
WHERE
DATE(transactions.created_at) = DATE(CURRENT_DATE)
AND transaction_type = 1
AND transaction_status = 2
GROUP BY
transaction_currency
突然之间,我不确定为什么,这个查询需要大约13秒 这是EXPLAIN:
查询时间突然增加的原因是什么?我该如何减少呢?
答案 0 :(得分:4)
如果要向表中添加更多数据,查询时间将会增加。
但你可以做一些事情来改善表现。
( transaction_type, transaction_status, created_at)
DATE()
函数(或任何函数),因为这不允许引擎使用索引。 CURRENT_DATE
是一个常数,所以没有关系,但是没有必要,因为已经返回DATE
created_at
不是日期,则可以使用created_at >= CURRENT_DATE and created_at < CURRENT_DATE + 1
答案 1 :(得分:1)
+1从@JuanCarlosOropeza回答,但你可以进一步了解索引。
ALTER TABLE transactions ADD INDEX (
transaction_type,
transaction_status,
created_at,
transaction_currency,
transaction_total
);
正如@RickJames在评论中提到的,列的顺序很重要。
我在演示文稿How to Design Indexes, Really中描述了有关索引设计的更多详细信息(视频:https://www.youtube.com/watch?v=ELR7-RdU9XU)。
你可能会坚持使用&#34;使用临时&#34;因为您有一个范围条件,并且还有一个GROUP BY引用不同的列。但你至少可以消除&#34;使用filesort&#34;通过这个技巧:
...
GROUP BY
transaction_currency
ORDER BY NULL
假设您查询结果的行返回的顺序并不重要。
答案 2 :(得分:0)
我不知道是什么让你的查询变慢了。更多数据?不成?新数据库版本?
然而,我很惊讶地发现没有索引真正支持查询。你应该有一个复合索引,从具有最高基数的列开始(日期?好吧,你可以尝试不同的列顺序,看看DBMS为查询选择了哪个索引)。
create index idx1 on transactions(created_at, transaction_type, transaction_status);
如果created_at
包含日期部分,那么您可能希望创建一个仅包含日期和索引的计算列created_on
。
您甚至可以将此索引扩展为覆盖索引(where子句字段后跟group by子句字段,后跟select子句字段):
create index idx2 on transactions(created_at, transaction_type, transaction_status,
transaction_currency, transaction_total);