Melhor desempenho em Associações
-
21-08-2019 - |
Pergunta
Agora eu tenho uma tabela chamada Campanhas que tem muitos hits, se eu chamar digamos:
Campaign.find(30).hits
O que leva 4 segundos, ou 4213 ms.
Se eu chamo isso de vez:
campaign = Campaign.find(30) campaign.hits.count
Será que ela ainda carregar todos os hits, em seguida, contar? Ou não vê que eu estou contando e evita carregar todos os hits? (Que é atualmente 300.000 linhas).
Eu estou tentando descobrir uma maneira inteligente de carga / contar meus sucessos. Eu estou pensando sobre a adição de um método para o meu modelo Campaign.rb, como:
def self.total_hits find :first, :select => 'COUNT(id) as hits', :conditions => ["campaign_id = ?", self.id] end
Eu sei que consulta não irá carregar a partir da tabela hits
, mas isso é apenas um exemplo de contá-lo a partir de uma consulta de auto feito, apposed para Ruby on Rails fazendo isso por mim.
Será que isso memcache consulta ser mais pesca? (Tenho que correr, mas não parece ser melhor mais rápido / mais lento, apenas a mesma velocidade /.)
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
Todas as sugestões seria ótimo!
Solução
Como sobre: ??
Campaign.find(30).hits.count
Você também pode considerar adicionando o seguinte em hit.rb
(assumindo uma relação de um-para-muitos entre campanhas e acessos).
belongs_to :campaign, :counter_cache => true
Você precisa então uma coluna na tabela de campaigns
chamado hits_count
. Isso vai evitar bater hits
completamente se você está recebendo apenas a contagem.
Você pode verificar o API para o resumo completo.
Outras dicas
Meu ActiveRecord pode ser um pouco enferrujado, então me perdoe se assim for, mas IIRC Campaign.find(30).hits
é pelo menos duas consultas separadas. Como é que Campaign.find(30, :include => [ :hits ]).hits
fazer? Isso deve executar uma única consulta.