首页 > 解决方案 > Mysql:相同的查询,相同数量的结果行,没有连接,慢 10 倍?

问题描述

我在包含 ~3M 行的 innodb 表上运行以下两个查询。出于某种原因,第一个查询需要不到一秒的时间来返回 168,199 行,而第二个查询需要 8 秒并返回 167,159 行?返回几乎相同结果所需的时间增加了 10 倍?

SELECT count(idActivities) as amt 
FROM Activities 
WHERE Data_Type='email' 
      AND Status='sent' 
      AND (Created > '2019-07-17 00:00:00' 
           AND Created <= '2019-08-17 00:00:00');

SELECT count(idActivities) as amt 
FROM Activities 
WHERE Data_Type='email' 
      AND Status='sent' 
      AND (Created > '2019-08-17 00:00:00' 
           AND Created <= '2019-09-17 00:00:00');

如果我从第二条语句中删除额外的 where 子句,例如

SELECT count(idActivities) as amt 
FROM Activities 
WHERE (Created > '2019-08-17 00:00:00' 
       AND Created <= '2019-09-17 00:00:00');

查询时间下降到半秒。如果我在语句中添加一个额外的 where 子句,例如 Data_Type= 或 Status= 它会跳回到 8 秒以上。

我也尝试将日期朝任一方向移动几天,但这不会影响查询时间。

该表在 idActivities、Data_Type、Status 和 Created 上建立索引。

服务器运行 5GB 内存,8 个内核,innodb_buffer_pool_size=3G,InnoDB 缓冲区使用率为 49%。

我在不同的服务器上尝试了相同的查询,结果大致相同,大约 4 秒,这仍然很慢。

我注意到的唯一区别是 Data_Type 列的基数不同,即使表几乎相同(它是前一天的备份)。

我将不胜感激任何帮助或帮助了解如何改善查询时间?运行“DISTINCT(Data_Type)”只为整个表返回 13 行。

已编辑 谢谢 Salman A,通过添加以下复合索引极大地提高了两个查询的性能:

CREATE INDEX ix_1 ON 活动(已创建、Data_Type、状态);

标签: mysqldatabase-performance

解决方案


我建议创建以下覆盖索引:

 CREATE INDEX ix_1 ON t (Data_Type, Status, Created)

列的顺序很重要。高基数列通常放在最前面,但是对于这个特定的查询,您需要将创建的列放在最后,因为它涉及范围比较(前两个需要相等比较)。


推荐阅读