В некоторых случаях, когда я получаю отношение ActiveRecord, я испытываю странное поведение с .each
в ActiveRecord::Relation
Кажется, когда ActiveRecord::Relation делегирует :each
в :to => :to_a
(источник)
@tasks = Task.find_task(list, {:week_id => 1})
По сути, есть длинный метод класса, который принимает объект (list
и хэш с :week_id
)
В этом методе find_task
происходит множество фильтров и запросов, но в итоге он возвращает отношение к @tasks
.
Затем в шаблоне у меня есть:
<% @tasks.each do |task| %>
.
.
.
<% end %>
По какой-то причине, независимо от размера @tasks
, это занимает ~3 минуты. Я могу воспроизвести это же поведение, вызвав @tasks.to_a
. Даже если @tasks
экземпляр ActiveRecord::Relation состоит только из двух записей, вызов to_a
для них занимает> 3 минуты.
Это происходит не на всех :week_id
, а только на определенном week_id, например: :week_id => 1
SQL выполняется нормально, и я возвращаю отношение, просто кажется, что это проблема с перечислением в конкретном ActiveRecord::Relation.
Обновить
Внутри алгоритма (я думаю, это означает метод класса) я делаю МНОГО нетерпеливой загрузки. Итак, Postgres выполняет много операций LEFT OUTER JOIN
, и я проиндексировал все таблицы, в которых это должно происходить.
Объясняющий анализ показывает, что все сканирования index scans
и, как выясняется, запрос выполняется просто отлично с большим количеством нетерпеливой загрузки... и я получаю нетерпеливо загруженный 'ActiveRecord::Relation` за разумное время.
Обновление 2 Пока этот процесс занимает 3 минуты, я вижу процесс postgres, работающий в течение нескольких секунд, а затем я вижу это в течение 3 минут в качестве вывода в top
:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8685 dylan 20 0 3407m 2.6g 904 R 99.7 69.1 1:14.49 /usr/local/bin/ruby script/rails s
Когда он наконец завершится, сервер покажет это;
- нетерпеливая загрузка:
200 ms
,139 ms
затем - большой SQL-запрос с большим количеством
LEFT OUTER JOINS in 33,000 ms
(длинный, но не там, где большинство), затем 257,000 ms
в шаблоне.
И когда я повторяю поведение в шаблоне, я вижу, что вызов to_a
для отношения @tasks
занимает ~3-4 минуты.
Итак, когда мой сервер сообщает мне, что все время потрачено на шаблон, и я вижу, что вызов перечислимого для отношения занимает вечность, это когда запрос выполняется? Хотя в top
я вижу только запущенный процесс ruby
?