Rails / Active Record .save! вопрос эффективности - PullRequest
1 голос
/ 13 августа 2011

Новичок в rails / ruby ​​(используется rails 3 и ruby ​​1.9.2), и я пытаюсь избавиться от некоторых ненужных выполняемых запросов.

Когда я бегу, каждый делает:

apples.to_a.each do |apple|
  new_apple = apple.clone
  new_apple.save!
end

и я проверяю sql LOG, я вижу три оператора выбора, за которыми следует один оператор вставки. Выбранные утверждения кажутся совершенно ненужными. Например, они что-то вроде:

ВЫБРАТЬ Fruit. * Из Fruits, где Fruit.ID = 5 LIMIT 1;
ВЫБЕРИТЕ Цвет. * Из Цветов, где Color.ID = 6 LIMIT 1;
SELECT TreeType. * Из TreeTypes, где TreeType.ID = 7 LIMIT 1;
ВСТАВИТЬ в значения Apple (Fruit_id, color_id, treetype_id) (6, 7, 8) ВОЗВРАЩАЯСЯ "id";

Похоже, это не займет много времени, но когда у меня будет 70 000 вставок, я держу пари, что эти три выбора для каждой вставки займут приличное количество времени.

Так что мне интересно следующее:

  • Это типично для ActiveRecord / Rails .save! метод, или предыдущий разработчик добавил какой-то собственный код?
  • Могут ли эти три оператора выбора, выполняемые для каждого элемента, вызвать заметное дополнительное время?
  • Если он встроен в rails / active record, легко ли его обойти, если это сделает его более эффективным?

Ответы [ 2 ]

3 голосов
/ 13 августа 2011

Вы должны проверять свои ассоциации при сохранении, чтобы такая вещь произошла, что-то вроде этого:

class Apple < ActiveRecord::Base
  validates :fruit,
    :presence => true
end

Чтобы подтвердить эту связь, запись должна быть загружена, и это должно произойтидля каждой проверки отдельно, для каждой записи по очереди.Это стандартное поведение save!

Вы можете сохранить без проверок, если вы хотите жить опасно:

apples.to_a.each do |apple|
  new_apple = apple.clone
  new_apple.save(:validate => false)
end

Лучшим подходом является манипулирование записями непосредственно в SQL путем массовоговставить, если ваша СУБД поддерживает это.Например, MySQL позволит вам вставлять тысячи строк одним вызовом INSERT.Обычно это можно сделать, используя уровень доступа Apple.connection, который позволяет выполнять произвольные вызовы SQL с такими вещами, как execute

0 голосов
/ 13 августа 2011

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

Обычно я не ожидал бы, что activerecord будет выполнять ненужный поиск - хотя это не означает, что он всегда эффективен ...

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