环境:Rails 2.3.11,MySQL 5.1(InnoDB)
My Rails应用程序偶尔会遇到简单查询问题,这些问题需要很长时间才能完成,并且会影响整个应用程序的更新能力。这些查询通常与论坛,网站的最高流量部分以及(到目前为止)最多更新的部分相关。以下是从MySQL慢速日志中提取的示例查询示例:
# Query_time: 46.900202 Lock_time: 0.000030 Rows_sent: 0 Rows_examined: 0
SET timestamp=1302172666;
UPDATE `forum_topics`
SET `views` = 153, `updated_at` = '2011-04-07 10:36:59'
WHERE `id` = 1213305;
这是一个非常简单查询,应该非常快,但在这种情况下,它需要将近47秒才能完成。此服务器上的平均负载不会超过2,因此这不是问题。其他一些兴趣点是:
views
和updated_at
都不是
索引。 我在这里寻找的是有关解决此问题的后续步骤的一些建议。
感谢。
P.S。架构/索引如下:
CREATE TABLE `forum_topics` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`forum_category_id` int(11) DEFAULT NULL,
`title` varchar(255) NOT NULL,
`sticky` tinyint(1) DEFAULT '0',
`views` int(11) DEFAULT '0',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`last_post_created_at` datetime DEFAULT NULL,
`slug` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_forum_topics_on_created_at` (`created_at`),
KEY `index_forum_topics_on_forum_category_id` (`forum_category_id`),
KEY `index_forum_topics_on_sticky` (`sticky`)
) ENGINE=InnoDB AUTO_INCREMENT=1215414 DEFAULT CHARSET=utf8;
答案 0 :(得分:1)
1)可能存在硬件错误 - 磁盘重置。 2)id键是否已编入索引? 3)通信问题。 4)是时间戳局部变量?如果它之前没有“@”吗?
答案 1 :(得分:1)
许多数据库产品突然失速的原因很多 - 而MySQL并不孤单。以下是一些例子:
您需要从存储中加载表描述(在forum_topics上没有可用的表缓存条目)。此操作是序列化 - 您可以排在另一个桌面上的另一个用户后面。
您正在使用查询缓存,查询缓存(可能)已碎片化。
InnoDB目前正在执行一项活动,例如扩展数据文件的大小,这会导致短暂停顿(也许你将auto_extend_increment设置为高?)
这些只是示例 - 肯定有更多原因。您需要做的是使用poor man's profiler等分析工具。它将为您提供有关查询被阻止的确切位置的堆栈跟踪。搜索bugs.mysql.com以获取堆栈跟踪,或尝试询问Percona forums之类的内容。
答案 2 :(得分:0)
尝试将LIMIT
添加到您的查询中。认为这应该是这样的:
... WHERE `id` = 1213305
LIMIT 1
答案 3 :(得分:0)
where子句通常是长时间运行查询的罪魁祸首。我可以看到,在此查询中,仅引用了“id”列。我会检查它是否已编入索引。如果是,我会检查它是否正确编入索引。如果索引已经存在,我甚至会尝试重新索引“id”列
答案 4 :(得分:0)
在桌面上运行优化可能会有所帮助,特别是如果磁盘上仍有大量已删除的行。
除此之外,EXPLAIN对该查询的了解是关于它如何运行(以及该查询的选择版本)
答案 5 :(得分:0)
这里没有足够的信息告诉您为什么您的查询正在缓慢执行,但是:
如果这是一个MYISAM表,这些更新可能需要很长时间,因为MYISAM缺少对表的行级锁定。这会影响您的查询性能,因为您需要运行的每个SELECT都会在表上获得READ LOCK(不允许进一步写入)。此外,MYISAM表上的UPDATE需要另一个锁,它阻止所有其他UPDATES / INSERTS / SELECTS运行。因此,如果您运行了10个这样的查询,它们就不会同时运行,并且必须等待彼此完成。
我不认为索引是你的问题,因为你提到了自动增量并使用ID字段进行更新,所以我确定这是你的主键。
答案 6 :(得分:0)
这有点旧,但我偶然发现它,也许对其他人有帮助......
如果遇到这样的问题,您可以使用内部探查器:
mysql> SET PROFILING=1;
mysql> [your query]
mysql> SHOW PROFILE FOR QUERY 1;
如果您的问题是随机发生的,则另一个进程可能已锁定该表。您可以使用SHOW FULL PROCESSLIST
和SHOW OPEN TABLES
来查看此内容。
此外,对于大表,您可能会遇到缓冲区的内存问题 - 有很多关于此的好页面。 http://dev.mysql.com/doc/refman/5.1/en/innodb-tuning.html和http://www.mysqlperformanceblog.com/2007/11/01/innodb-performance-optimization-basics/是一个很好的开始