Ruby on Rails: Model.all.each против find_by_sql («SELECT * FROM model»). Каждый? - PullRequest
3 голосов
/ 30 марта 2010

Я довольно новичок в RoR. В моем контроллере я перебираю каждый кортеж в базе данных. Для каждой таблицы, для каждого столбца я звонил

SomeOtherModel.find_by_sql("SELECT column FROM model").each {|x| #etc }

, который работал достаточно хорошо. Когда я позже изменил это на

Model.all(:select => "column").each {|x| #etc }

цикл начинается примерно с той же скоростью, но быстро замедляется примерно до 100 раз медленнее, чем команда find_by_sql. Эти звонки должны быть идентичны, поэтому я действительно не знаю, что происходит.

Я знаю, что эти вызовы не самые эффективные, но это всего лишь промежуточный шаг, и я буду оптимизировать его еще раз, когда он будет работать правильно.

Итак, поясним: почему в мире вызов Model.all.each выполняется намного медленнее, чем использование find_by_sql.each?

Спасибо!

Ответы [ 2 ]

7 голосов
/ 30 марта 2010

Оба вызова выполняют один и тот же вызов SQL, поэтому они должны иметь примерно одинаковую скорость. Model.all проходит дополнительный уровень косвенности. Я думаю, что Rails в all собирает все строки из соединения с БД, затем вызывает эту коллекцию как параметр другого метода, который проходит по этой коллекции и создает объекты модели. В find_by_sql все это делается в 1 методе. Может быть, это немного быстрее. Насколько велик ваш набор данных? Если набор содержит более 100 записей, вы не должны использовать все, но используйте find_in_batches. Он использует ограничения и смещения для запуска вашего кода в пакетном режиме и не загружает всю таблицу сразу в память. Вам нужно включить первичный ключ в выбор, так как он использует его для выполнения порядка и ограничения. Пример:

Model.find_in_batches(:batch_size => 100) do |group|
  group.each {|item| item.do_something_interesting }
end
2 голосов
/ 01 декабря 2010

СкоттД правильно. Вызов find_by_sql не создает замедления, которое вы видите B_. Проблемы со скоростью связаны с тем, что Model.all загружает экземпляр модели в память для каждой выбранной записи. Это может привести к полному отказу с достаточно большим набором результатов. К вашему сведению, это очень хорошо описано в Руководстве по Rails здесь: http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...