我有一个简单的Rails应用程序的文章和评论在MySQL 5.5和Ruby 1.9.3运行和轨道3.2.12:为什么ActiveRecord destroy_all需要这么久?
class Article < ActiveRecord::Base
attr_accessible :body, :title
has_many :comments
end
class Comment < ActiveRecord::Base
attr_accessible :content
belongs_to :article
end
我已经产生了大量的评论的一篇文章,而现在想删除他们都在铁轨控制台:
$ rails c
Loading development environment (Rails 3.2.12)
[1] pry(main)> a = Article.find(1)
(2.0ms) SET SQL_AUTO_IS_NULL=0
Article Load (8.0ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`id` = 1 LIMIT 1
=> #<Article id: 1, title: "Test", body: "---\n- Est vel provident. Laboriosam dolor asperiore...", created_at: "2013-05-17 09:54:54", updated_at: "2013-05-21 14:52:18">
[2] pry(main)> require 'benchmark'
[3] pry(main)> puts Benchmark.measure { a.comments.destroy_all }
Comment Load (896.0ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
EXPLAIN (2.0ms) EXPLAIN SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
EXPLAIN for: SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
+----+-------------+----------+------+---------------+------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------------+---------+-------+-------+-------------+
| 1 | SIMPLE | comments | ref | article_id | article_id | 5 | const | 48186 | Using where |
+----+-------------+----------+------+---------------+------------+---------+-------+-------+-------------+
1 row in set (0.00 sec)
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 2
SQL (2.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 3
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 4
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 5
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 6
SQL (5.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 7
SQL (2.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 8
SQL (2.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 9
. . .
SQL (0.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 37360
SQL (0.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 37361
最后查询删除最后一个注释,然后该过程将挂起有一个非常长的时间才终于回到提交之前:
(1.9ms) COMMIT
690.380000 1.390000 691.770000 (693.885877)
SHOW PROCESSLIST
确认没有锁:
mysql> show processlist;
+----+----------+-----------+------------------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+----------+-----------+------------------+---------+------+-------+------------------+
| 6 | bloguser | localhost | blog_development | Query | 0 | NULL | show processlist |
| 7 | bloguser | localhost | blog_development | Sleep | 459 | | NULL |
+----+----------+-----------+------------------+---------+------+-------+------------------+
2 rows in set (0.00 sec)
delete_all
与dependent: :destroy
或dependent: :delete_all
显示出非常相似的行为。
流行的看法似乎是,destroy_all
的问题在于它实例化所有对象并逐个删除它们,但它看起来不像是这里的问题。在所有的DELETE
s被执行之后以及在COMMIT
最终被调用之前需要花费这么长的时间?
看看我更新的答案,看看它是否结合上述多一点光。 – TreyE