我正在使用MySQL5.7。
有一张table叫 transactions
有超过300万张唱片。表架构如下: id
-int(自动递增) deleted_at
(datetime,允许为空) record_status
(tinyint,默认值为1)
与此表相关的其他列。。。
这个 record_status
是的整数版本 deleted_at
. 删除记录时,该值设置为0。还会为此列创建索引。
基于null的datetime查询需要 740 ms
执行: select transactions.id from transactions where transactions.deleted_at is null
基于tinyint的查询 15.1 s
执行: select transactions.id from transactions where transactions.record_status = 1
对tinyint列(带索引)的检查不应该更快吗?为什么会这样?
[编辑]
添加了有关表性能的信息
为了进一步实验,所有不必要的列都从表中删除了。只有以下情况仍然存在。 id
-int(自动递增) deleted_at
(datetime,允许为空) record_status
(tinyint,默认值为1) transaction_time
(日期时间)
查询1:需要2.3ms
select transactions.id from transactions
where transactions.record_status = 1 limit 1000000;
查询2:需要2.1ms
select transactions.id from transactions
where transactions.deleted_at is null limit 1000000;
查询3:需要20秒
select transactions.id from transactions
where transactions.record_status = 1
and transaction_time > '2020-04-01' limit 1000;
查询4:需要500毫秒
select transactions.id from transactions
where transactions.deleted_at is null
and transaction_time > '2020-04-01' limit 1000;
查询5:394ms
select transactions.id from transactions
where transaction_time > '2020-04-01' limit 1000000;
我不明白为什么查询3要花这么长时间。
2条答案
按热度按时间a6b3iqyw1#
通过增加一个综合指数来解决这个问题。
以下两种方法现在都可以提高性能。
复合键打开
transaction_time
以及deleted_at
.复合键打开
transaction_time
以及record_status
.多亏了@gordon linoff和@jarlh。他们的建议导致了这一发现。
q1qsirdb2#
没有这样的复合索引就无法进行优化--按以下顺序:
(不,两个单独的单列索引将不起作用。)