查询时间突然增加

时间:2017-09-05 14:01:13

标签: mysql datetime indexing mariadb query-performance

我有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: enter image description here

这些是交易表的所有索引: enter image description here

查询时间突然增加的原因是什么?我该如何减少呢?

3 个答案:

答案 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在评论中提到的,列的顺序很重要。

  • 首先,平等比较中的列
  • 接下来,您可以索引用于范围比较的一个列(除了相等之外的任何内容),或者GROUP BY或ORDER BY。您同时具有范围比较和GROUP BY,但您只能获取索引以帮助其中一个。
  • 最后,如果您认为可以获得覆盖索引,则查询需要其他列。

我在演示文稿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);