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小时+的主要内容,如果未能解决你的问题,请参考以下文章