mysql - 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、状态);
解决方案
我建议创建以下覆盖索引:
CREATE INDEX ix_1 ON t (Data_Type, Status, Created)
列的顺序很重要。高基数列通常放在最前面,但是对于这个特定的查询,您需要将创建的列放在最后,因为它涉及范围比较(前两个需要相等比较)。
推荐阅读
- c# - 从另一个脚本销毁游戏对象
- java - 将矩阵减少到每个单元格一个元素
- ios - 由 navigationController 呈现时未调用 ViewWill/DidAppear
- java - SpringDoc WebMvc 与 WebFlux
- mysql - 导入 50GB SQL 冻结或无法完成
- javascript - 如何使用 jQuery 从另一个网站下载文件?
- linux - 如何在没有换行符的情况下替换文件中的子字符串?
- python - 列表理解代替嵌套循环避免项目重复
- javascript - 未捕获的 SyntaxError 意外标识符
- python - Python,Pandas 根据索引值创建列