2009-02-04 5 views
2

En ce moment, j'ai appelé une table campagnes qui a de nombreux succès, si je l'appelle dit:une meilleure performance sur les associations

Campaign.find(30).hits

qui prend 4 secondes, ou 4213 ms.

Si j'appelle ceci:

 
campaign = Campaign.find(30) 
campaign.hits.count 

chargement est-il encore tous les coups, puis compte? Ou voit-il que je compte et évite de charger tous les hits? (Qui est actuellement 300 000+ lignes).

J'essaie de trouver une façon intelligente de charger/compter mes hits. Je pense à l'ajout d'une méthode pour mon modèle Campaign.rb, comme:

 
def self.total_hits 
    find :first, :select => 'COUNT(id) as hits', :conditions => ["campaign_id = ?", self.id] 
end 

Je sais que la requête ne se charge pas de la table hits, mais qui est juste un exemple de compter à partir d'une requête en auto , apposé à Ruby on Rails faisant cela pour moi.

Cette requête memcache serait-elle plus efficace? (Je l'ai en cours d'exécution, mais ne semble pas être mieux/plus rapide/plus lent, juste la même vitesse.)

 
def self.hits 
    Rails.cache.fetch("Campaign_Hits_#{self.campaign_id}", :expires_in => 40) { 
     find(:first, :select => 'COUNT(id) as hits', :conditions => ["campaign_id = ?", self.campaign_id]).hits 
    } 
end 

Toute suggestion serait génial!

Répondre

6

Que diriez-vous:

Campaign.find(30).hits.count 

Vous pouvez également envisager d'ajouter ce qui suit dans hit.rb (en supposant un à plusieurs entre les campagnes et les coups).

belongs_to :campaign, :counter_cache => true 

Vous devez ensuite une colonne dans la table campaigns appelée hits_count. Cela évitera de frapper hits si vous obtenez seulement le compte.

Vous pouvez consulter le API pour le détail complet.

+0

Erreur indéfinie, il ne devrait pas savoir pour trouver le 30 ID de toute façon. – Garrett

+0

Oh! Cela a l'air génial, merci! – Garrett

1

Mon ActiveRecord peut être un peu rouillé, alors pardonnez-moi si c'est le cas, mais IIRC Campaign.find(30).hits est au moins deux requêtes distinctes. Comment fonctionne Campaign.find(30, :include => [ :hits ]).hits? Cela devrait effectuer une seule requête.

+0

Je crois qu'il fait la même chose dans ce cas. Deux requêtes seraient plus efficaces ici de toute façon, puisque vous ne voudriez pas que LEFT REJOIGNE tous les hits sur la ligne de la campagne. Tout ce dont vous avez besoin est essentiellement "WHERE campaign_id = 30" –

Questions connexes