mysql查询慢--2小时+

Posted

技术标签:

【中文标题】mysql查询慢--2小时+【英文标题】:Slow mysql query--2 hours+ 【发布时间】:2021-01-16 03:40:32 【问题描述】:

您好,这是我的查询,大约需要一个小时才能完成。该表是 innodb 中的 700 万条记录。我在(时间戳,符号)上有一个索引。 Test7() 是用于得出前一周日期的函数。 我正在使用 mysql 5.3。关于如何加快速度的任何建议?谢谢

'''''''''''

SELECT Archive_dataPolygon.timeStamp,
Archive_dataPolygon.symbol,
Archive_dataPolygon.open,
Archive_dataPolygon.high,
Archive_dataPolygon.low,
Archive_dataPolygon.close,
Archive_dataPolygon.volume,
Archive_dataPolygon.afterHours,
Archive_dataPolygon.preMarket,
d2.timeStamp,
d2.symbol,
d2.open,
d2.high,
d2.low,
d2.close,
d2.volume,
d2.afterHours,
d2.preMarket,
d3.timeStamp,
d3.symbol,
d3.open,
d3.high,
d3.low,
d3.close,
d3.volume,
d3.afterHours,
d3.preMarket,
d4.timeStamp,
d4.symbol,
d4.open,
d4.high,
d4.low,
d4.close,
d4.volume,
d4.afterHours,
d4.preMarket,
round((Archive_dataPolygon.high-Archive_dataPolygon.open)/Archive_dataPolygon.open,3) as 'quoteChangePercent'

from Archive_dataPolygon
inner join Archive_dataPolygon d2 force index(timeStampSymbol) on d2.symbol=Archive_dataPolygon.symbol and d2.timeStamp = test7(Archive_dataPolygon.timeStamp)
inner join Archive_dataPolygon d3 on d3.symbol=Archive_dataPolygon.symbol and d3.timeStamp = test7(d2.timeStamp)
inner join Archive_dataPolygon d4 on d4.symbol=Archive_dataPolygon.symbol and d4.timeStamp = test7(d3.timeStamp)

where Archive_dataPolygon.timeStamp < NOW() - interval 4 day and Archive_dataPolygon.timeStamp > NOW() - INTERVAL 20000 DAY and Archive_dataPolygon.open >= 50 and Archive_dataPolygon.open <= 70 and Archive_dataPolygon.symbol not IN("%Nasdaq%") and round((Archive_dataPolygon.high-Archive_dataPolygon.open)/Archive_dataPolygon.open,3)=%quoteChangePercent%


HAVING isnull(Archive_dataPolygon.timeStamp)=false and isnull(d2.timeStamp)=false and isnull(d3.timeStamp)=false and isnull(d4.timeStamp)=false

order by Archive_dataPolygon.timeStamp desc
LIMIT 2000

'''''''''''''''

【问题讨论】:

函数不能使用索引,所以无论test7() 是什么,它都会破坏性能(假设timestamp 被索引)。 IN("%Nasdaq%") 不能使用索引;这似乎是您的数据模型中的一个缺陷。 %quoteChangePercent% 看起来像一个错误。 HAVING 通常保留用于汇总结果,所以我怀疑它在这里的使用。 WHERE... IS NOT NULL 会更常见。 虽然它对性能没有影响,但为所有表实例设置别名并没有什么害处。 而且...您的结果集很难使用,因为区分 d2、d3 等很棘手 【参考方案1】:

代替

d2.timeStamp = test7(Archive_dataPolygon.timeStamp)

使用

Archive_dataPolygon.timeStamp = d2.timeStamp - INTERVAL 7 DAY

d2.timeStamp = Archive_dataPolygon.timeStamp + INTERVAL 7 DAY

(尝试每种方法;我无法轻易判断哪种方法更好。)

我希望timeStamp 的类型是“DATE”。请为每张桌子提供SHOW CREATE TABLE

没有 MySQL 5.3;也许您的意思是 MariaDB 5.3?提供SHOW VARIABLES LIKE 'version';

这没有过滤,对吗?如果没有,请忽略它:

Archive_dataPolygon.timeStamp > NOW() - INTERVAL 20000 DAY

这是什么?

HAVING  isnull(d2.timeStamp)=false

可以(应该)简化为

HAVING  d2.timeStamp IS NOT NULL

此时,可以将测试放入WHERE 子句中(因为您使用的是JOIN 而不是LEFT JOIN)。

如果您打算拥有LEFT JOIN,请详细说明您的目标。

这看起来很奇怪:

order by  Archive_dataPolygon.timeStamp desc LIMIT  2000

您想要最古老的记录,不管符号是什么?

通常我会推荐这个索引顺序:(symbol, timeStamp)。通常,在任何复合索引中使用使用= first 测试的列更为理想。 [但是,它可能对 this 查询的性能没有帮助。] 包括两个索引。

真正的杀手可能是test7()。我希望在我的其他建议之后,它只会触及 2000 行——乘以 4(由于 JOIN)。

如果您在我的建议后仍然需要帮助,请提供EXPLAIN SELECT

【讨论】:

以上是关于mysql查询慢--2小时+的主要内容,如果未能解决你的问题,请参考以下文章

MySQL的alter table查询非常慢

MySql分页查询慢|这里告诉你答案

mysql怎么开启慢查询日志开启

mysql 慢日志怎么按时间查询

常见Mysql的慢查询优化方式

mysql慢查询及查询优化