我有很多重复的记录,我正在努力剔除,为了做到这一点,我目前正在运行:

Survey.active.each do |survey|
  survey.response_sets.completed.each do |set|
    answer_ids = []
    set.responses.each do |r|
      if r.answer.blank?
        r.destroy
      else
        if answer_ids.include? r.answer_id
          r.destroy
        else
          answer_ids << r.answer_id
        end
      end
    end
  end
end

它查找所有活动调查,获取每个调查的响应集,然后获取每个响应集的单个响应。
然后根据响应集中的另一个响应是否存在answer_id来查看响应是否重复。在给定的响应集中,对于给定的answer_id,只能有一个响应。所以,如果有副本,它会销毁副本。
超过几十万排,进展非常缓慢。
那么,我怎样才能加快这个过程呢?
下面是对其中每一个的sql调用:
Survey.active
SELECT "surveys".* FROM "surveys" WHERE "surveys"."active" = 't'

survey.response_sets.completed
SELECT "response_sets".* FROM "response_sets" WHERE ("response_sets".survey_id = 12345) AND (completed_at IS NOT NULL)

set.responses
SELECT "responses".* FROM "responses" WHERE ("responses".response_set_id = 54321)

我正在运行Rails3.0.6和PostgreSQL。

最佳答案

我想你可能是从错误的角度来攻击这件事。首先,您不应该允许坏数据进入数据库。我真的看不到数据库模型的样子,但是模型中的一些验证可能会阻止您这样清理数据库。在rails中加载非常大的数据集是一件痛苦的事情,而且它非常慢,而且内存也非常匮乏。

# maybe something like this?
class Responses < ActiveRecord::Base
  validates_uniqueness_of :answer_id, :scope => :id
end

批处理提示(添加)
activerecord在处理大型结果集时并不能很好地工作。如果您有will_paginate或类似的东西,您可以很容易地在完整的数据集中分段循环。
(1..Survey.total_pages).each do |p|
   Survey.paginate(:page => p, :per_page => 30).each do |survey|
     # your loop but with less memory overhead

关于sql - 我如何加快这段代码的速度?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8807499/

10-13 05:39