title: Why is ActiveRecord destroy_all taking so long?
body: <p>I have a simple rails app with articles and comments running on MySQL 5.5, Ruby 1.9.3 and rails 3.2.12:</p>
  
  <pre><code>class Article &lt; ActiveRecord::Base                                                                                   
    attr_accessible :body, :title
    has_many :comments
  end   
  
  class Comment &lt; ActiveRecord::Base
    attr_accessible :content
    belongs_to :article
  end
  </code></pre>
  
  <p>I have generated lots of comments for an article, and am now trying to delete them all in the rails console:</p>
  
  <pre><code>$ rails c 
  Loading development environment (Rails 3.2.12)
  [1] pry(main)&gt; 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
  =&gt; #&lt;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"&gt;
  [2] pry(main)&gt; require 'benchmark'
  [3] pry(main)&gt; 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
  </code></pre>
  
  <p>The last query is deleting the last comment, and the process then hangs there for a <em>very</em> long time before finally returning and committing:</p>
  
  <pre><code>   (1.9ms)  COMMIT
  690.380000   1.390000 691.770000 (693.885877)
  </code></pre>
  
  <p><code>SHOW PROCESSLIST</code> confirms that there is no lock:</p>
  
  <pre><code>mysql&gt; 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)
  </code></pre>
  
  <p><code>delete_all</code> with <code>dependent: :destroy</code> or <code>dependent: :delete_all</code> show a very similar behaviour.</p>
  
  <p>The popular belief seems to be that the issue with <code>destroy_all</code> is that it instantiates all the objects and deletes them one by one, but it doesn't look like it's the problem here.  What is taking so long to process after all the <code>DELETE</code>s have been executed, and before <code>COMMIT</code> is finally called?</p>