间歇性地缓慢的Mysql表 - 为什么?

时间:2009-08-10 09:31:33

标签: mysql ruby-on-rails performance intermittent

我们最近遇到过一个我以前从未见过的问题,大约3个小时,我们的一个Mysql表变得非常慢。此表包含论坛帖子,目前大约有一百万行。变慢的查询在我们的应用程序中非常常见:

SELECT * FROM `posts` WHERE (`posts`.forum_id = 1)  ORDER BY posts.created_at DESC LIMIT 1;

我们在(forum_id,created_at)上的posts表上有一个索引,它通常允许在内存中进行此查询和排序。但是,在这三个小时内,并非如此。什么是通常的即时查询,范围从这段时间内的2秒-45秒。然后它恢复正常。

我通过慢速查询日志进行了仔细研究,没有其他任何看起来与众不同。我查看了New Relic(这是一个Rails应用程序),所有其他操作的运行速度与正常情况基本相同。我们今天没有异常数量的留言。我在日志中找不到任何其他奇怪的东西。当数据库仍然可以使用时,数据库没有交换。

我想知道Mysql是否可以来回改变用于给定查询的索引,无论出于何种原因,它开始决定今天在这个查询上进行全表扫描几个小时?但如果这是真的,为什么它会停止进行全表扫描?

有没有其他人遇到过一个间歇性的慢查询而无法理由?或者你对如何调试这样的问题有什么创意吗?

2 个答案:

答案 0 :(得分:2)

我会尝试MySQL EXPLAIN声明......

EXPLAIN SELECT * FROM `posts` WHERE (`posts`.forum_id = 1)  ORDER BY posts.created_at DESC LIMIT 1;

可能值得检查Rails代码中的MySQL响应时间,如果超过阈值,则运行EXPLAIN并在某处记录详细信息。

Table locking也让人想起 - 当SELECT正在进行时,是否通过cronjob或大量查询更新了posts表?

希望有所帮助!

答案 1 :(得分:2)

在我工作的网站上,我们最近从MyISAM切换到InnoDB,并we found that some simple select queries which had both WHERE and ORDER BY clauses were using the index for the ORDER BY clause,导致进行表扫描以找到所需的几行(但是,哎呀,他们不需要在排序时进行排序它终于找到了所有!)

如链接文章中所述,如果您有一个小的LIMIT值,您的ORDER BY子句是主键的第一个成员(因此文件中的数据按其排序),并且有许多结果与您的匹配WHERE子句,使用ORDER BY索引对MySQL来说并不是一个坏主意。但是,我认为created_at不是主键的第一个成员,所以在这种情况下它不是一个特别聪明的想法。

我不知道为什么MySQL如果你没有改变任何东西就会切换索引,但我建议你尝试在相关的表上运行ANALYZE TABLE。如果结果集足够小,您也可以更改查询以删除LIMIT和ORDER BY子句并在应用程序级别进行排序;或者你可以添加a USE INDEX hint所以它永远不会猜错。

您还可以change the wait_timeout value to something smaller,以便使用错误索引的这些查询永远不会完成(但也不会滞后所有合法查询)。即使使用较小的wait_timeout,您仍然可以交互式地运行长查询,因为有一个单独的配置参数。