查询时间突然增加
Query time suddenly increased
我有 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 秒。
这是解释:
这些是交易的所有索引table:
查询时间突然增加是什么原因?我怎样才能减少它?
如果您向 table 添加更多数据,查询时间将会增加。
但是您可以做一些事情来提高性能。
- 为
( transaction_type, transaction_status, created_at)
创建复合索引
- 从您的字段中删除
DATE()
函数(或任何函数),因为那样不允许引擎使用索引。 CURRENT_DATE
是一个常数,所以没有关系,但不是必需的,因为已经 return DATE
- 如果
created_at
不是您可以使用的日期
created_at >= CURRENT_DATE and created_at < CURRENT_DATE + 1
- 或创建一个不同的字段以仅保存日期部分。
我不知道是什么让您的查询变慢了。更多数据?碎片化?新数据库版本?
然而,令我惊讶的是,并没有真正支持查询的索引。您应该有一个从具有最高基数的列开始的复合索引(日期?好吧,您可以尝试不同的列顺序并查看 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);
+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 (video: https://www.youtube.com/watch?v=ELR7-RdU9XU)。
您可能受困于 "using temporary",因为您有范围条件以及引用不同列的 GROUP BY。但是你至少可以通过这个技巧来消除"using filesort":
...
GROUP BY
transaction_currency
ORDER BY NULL
假设查询结果 return 中的行排序对您来说并不重要。
我有 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 秒。
这是解释:
这些是交易的所有索引table:
查询时间突然增加是什么原因?我怎样才能减少它?
如果您向 table 添加更多数据,查询时间将会增加。
但是您可以做一些事情来提高性能。
- 为
( transaction_type, transaction_status, created_at)
创建复合索引 - 从您的字段中删除
DATE()
函数(或任何函数),因为那样不允许引擎使用索引。CURRENT_DATE
是一个常数,所以没有关系,但不是必需的,因为已经 returnDATE
- 如果
created_at
不是您可以使用的日期 created_at >= CURRENT_DATE and created_at < CURRENT_DATE + 1
- 或创建一个不同的字段以仅保存日期部分。
- 如果
我不知道是什么让您的查询变慢了。更多数据?碎片化?新数据库版本?
然而,令我惊讶的是,并没有真正支持查询的索引。您应该有一个从具有最高基数的列开始的复合索引(日期?好吧,您可以尝试不同的列顺序并查看 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);
+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 (video: https://www.youtube.com/watch?v=ELR7-RdU9XU)。
您可能受困于 "using temporary",因为您有范围条件以及引用不同列的 GROUP BY。但是你至少可以通过这个技巧来消除"using filesort":
...
GROUP BY
transaction_currency
ORDER BY NULL
假设查询结果 return 中的行排序对您来说并不重要。