У меня есть много дубликатов записей, которые я пытаюсь отсеять, и сделать это, я в настоящее время работаю следующим образом:Как я могу ускорить этот блок кода?
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)
Я бегу Rails 3.0.6 и PostgreSQL.
Просто общий совет SQL, спросите себя, действительно ли вам нужно 'SELECT *' на все ваши запросы? К сожалению, я не знаю ни Ruby, ни RoR, которые помогут вам :( –
вы можете попробовать использовать хэш для отслеживания answer_ids, который вы уже видели, а не массива. Возможно, вы также захотите добавить некоторые дополнения и использовать find_each, а не каждый в самом внешнем цикле (в противном случае вы будете хранить все объекты, которые вы ранее смотрели на резидентные в ram). Очевидно, убедитесь, что у вас есть индексы во всех соответствующих столбцах. Изменение 'r.answer.blank?' на 'r. answer_id.blank' сэкономит много запросов (но если у вас нет внешних ключей, значит, вы не поймаете «болтающиеся» answer_ids –
Попробуйте обернуть весь smash в транзакции ('Survey.transaction do' ... 'end'), что может позволить Postgresql идти быстрее. Также посмотрите, можете ли вы просто использовать psql для непосредственного управления postgres для очистки, минуя рельсы/activerecord. –