2011-08-12 3 views
1

Nouveau sur rails/ruby ​​(en utilisant les rails 3 et ruby ​​1.9.2), et j'essaie de me débarrasser de certaines requêtes inutiles en cours d'exécution.Rails/Enregistrement actif .save! question d'efficacité

Quand je suis en cours d'exécution un chacun fait:

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

et je consulter le journal sql, je vois trois instructions select suivie d'une instruction d'insertion. Les instructions select semblent complètement inutiles. Par exemple, ils sont quelque chose comme:

SELECT Fruit. * À partir de fruits où Fruit.ID = 5 LIMITE 1;
SELECT Couleur. * À partir de Couleurs où Color.ID = 6 LIMIT 1;
SELECT TreeType. * À partir de TreeTypes où TreeType.ID = 7 LIMIT 1;
INSERT dans les valeurs Apples (Fruit_id, color_id, treetype_id) (6, 7, 8) RETURNING "id";

Apparemment, cela ne prendrait pas beaucoup de temps, mais quand j'ai des insertions de 70k à courir, je parie que ces trois sélections pour chaque insertion prendront un temps décent.

Je me demande donc les suivantes:

  • Est-ce typique de ActiveRecord/Rails .Save! méthode, ou le développeur précédent a-t-il ajouté un code personnalisé?
  • Ces trois instructions de sélection, exécutées pour chaque élément, entraîneraient-elles une perte de temps notable?
  • S'il est intégré dans des rails/enregistrement actif, serait-il facilement contourné, si cela le rendrait plus efficace?

Répondre

3

Vous devez être en train de valider vos associations lors de l'enregistrement d'une telle chose se produire, quelque chose comme ceci:

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

Afin de valider que la relation, le dossier doit être chargé, et cela doit se produire pour chaque validation individuellement, pour chaque enregistrement à son tour. C'est le comportement standard de save!

Vous pourriez sauver sans validation si vous vous sentez comme vivre dangereusement:

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

La meilleure approche est de manipuler les enregistrements directement dans SQL en faisant un insert de masse si votre SGBDR supporte . Par exemple, MySQL vous permettra d'insérer des milliers de lignes avec un appel INSERT. Vous pouvez généralement le faire en utilisant la couche d'accès Apple.connection qui vous permet de faire des appels SQL arbitraire avec des choses comme execute

0

Je suppose qu'il ya un before_save EDIT: (ou une validation comme suggéré ci-dessus) être la méthode appelé qui cherche la couleur et le type du fruit et le stocker avec le reste des attributs lorsque le fruit est enregistré - dans ce cas, ces recherches sont nécessaires ...

Normalement, je ne m'attendrais pas à faire l'enregistrement recherches inutiles - bien que cela ne signifie pas que c'est toujours efficace ...

+0

Pour être juste, ActiveRecord ne fait que ce que vous lui dites de faire même si parfois vous faites pas réaliser ce que vous lui dites de faire. – tadman