2010-08-20 4 views
0

Dans Rails lors de l'utilisation de activeRecord, pourquoi les requêtes de jointure sont-elles considérées comme incorrectes?Optimisation des rails Question

Par exemple

Ici, je suis en train de trouver le nombre d'entreprises qui appartiennent à une certaine catégorie.


    class Company ActiveRecord::Base 
    has_one :company_profile 
    end 

Trouver le numéro de la société pour un category_id particulier

 
number_of_companies = Company.find(:all, :joins=>:company_profile, :conditions=>["(company_profiles.category_id = #{c_id}) AND is_published = true"]) 

Comment cela pourrait être mieux ou est-ce juste une mauvaise conception?

 

    company_profiles = CompanyProfile.find_all_by_category_id(c_id) 
    companies = [] 
    company_profiles.each{|c_profile| companies.push(c_profile.company) } 
 

est-il pas mieux que la première demande crée une seule requête alors que je serais en cours d'exécution de plusieurs requêtes pour le second cas.

Quelqu'un pourrait-il expliquer pourquoi les jointures sont considérés comme une mauvaise pratique dans Rails

Merci à l'avance

+1

Pourriez-vous ajouter des références:Je n'étais pas au courant qu'une telle opinion était généralement tenue - AFAIK, c'est quelque chose à éviter à moins que vous en ayez besoin mais quand vous en avez besoin (typiquement pour des raisons de performance) alors vous devriez absolument le considérer - c'est pourquoi c'est là. Cela dit, je pense que l'exemple spécifique que vous donnez pourrait être traité le plus efficacement en utilisant count() avec les conditions appropriées. (Si vous avez seulement besoin d'un numéro, c'est) –

+0

Je semble avoir trouvé de l'aide ici http://akitaonrails.com/2008/05/25/rolling-with-rails-2-1-the-first- full-tutorial-part-2 – Sid

+0

Il semble qu'il n'y ait pas de règle générale contre l'utilisation de jointures mais lorsque vous avez beaucoup de jointures, cela implique que vos associations ne sont pas correctement conçues. – Sid

Répondre

1

À ma connaissance, il n'y a pas une telle règle. La règle est de frapper la base de données au minimum, et les rails vous donnent les bons outils pour cela, en utilisant les jointures.

L'exemple donné ci-dessus par Sam est exemplaire. Code simple, mais les coulisses des coulisses doivent faire deux requêtes, au lieu d'une seule utilisant une jointure. S'il y a une règle qui me vient à l'esprit, c'est d'éviter SQL là où c'est possible et d'utiliser autant que possible les rails. Cela maintient votre base de données de code agnostique (car les rails gère les différences pour vous). Mais parfois, même cela est inévitable. Il s'agit d'une bonne conception de base de données, en créant les index corrects (que vous devez définir manuellement dans les migrations), et parfois de grandes structures imbriquées/jointures sont nécessaires.

0

Si vous voulez juste trouver le nombre d'entreprises sur une catégorie tout ce que vous devez faire est de trouver la catégorie puis appelez le nom et la taille de l'association car il retournera un tableau.

@category = Category.find(params[:id]) 
@category.companies.size 
+0

Je comprends cela, ma question vise à comprendre pourquoi les requêtes jointes sont considérées comme mauvaises. Je suis désolé si ma question n'est pas très claire. – Sid

+0

Je pense que vous le rendez plus difficile que c'est parce que tout simplement les jointures ajoutent deux fois le travail où si vous collez avec un modèle sa moitié du travail. – s84

+0

Vous devriez écrire '@category = Category.find (params [: id],: include =>: entreprises)' ou bien vous utilisez deux fois la base de données. Concernant votre commentaire ci-dessus: plutôt le contraire. – nathanvda

1

Les requêtes jointes ne sont pas mauvaises, en fait, elles sont bonnes, et ActiveRecord les a en son coeur. Vous n'avez pas besoin de pénétrer dans find_by_sql pour les utiliser, des options comme: include le gèreront pour vous. Vous pouvez rester dans l'ORM, ce qui donne la lisibilité et la facilité d'utilisation, tout en créant des SQL très efficaces (à condition que vos index soient corrects!)

Résultat: vous devez faire le strict nécessaire minimum d'opérations de base de données. Les jointures sont un bon moyen de laisser la base de données faire le travail lourd pour vous, et de réduire le nombre de requêtes que vous exécutez.

Par le par, DataMapper et Arel (le moteur de recherche dans Rails 3) présentent beaucoup de chargement paresseux - cela signifie que le code tel que:

@category = Category.find(params[:id]) 
@category.companies.size 

entraînerait très probablement une requête de jointure qui ne a effectué une opération COUNT, car la première ligne n'entraînerait pas l'envoi d'une requête à la base de données.