Mejor rendimiento de Asociaciones
-
21-08-2019 - |
Pregunta
En este momento tengo una tabla llamada Campañas que tiene muchos golpes, si llamo a decir:
Campaign.find(30).hits
Lo que tarda 4 segundos, o 4213 ms.
Si llamo a esto en su lugar:
campaign = Campaign.find(30) campaign.hits.count
¿Todavía cargar todos los golpes, luego contar? ¿O ver Cuento y evita cargar todos los éxitos? (Que actualmente es de 300.000 filas).
Estoy tratando de encontrar una manera inteligente para cargar / recuento de mis éxitos. Estoy pensando en añadir un método para mi modelo Campaign.rb, como:
def self.total_hits find :first, :select => 'COUNT(id) as hits', :conditions => ["campaign_id = ?", self.id] end
Sé que la consulta no se carga desde la mesa hits
, pero eso es sólo un ejemplo de contarlo de una consulta hecho a sí mismo, él se ponga a Ruby on Rails haciendo esto por mí.
Sería esta consulta Memcache ser más eficiente? (Tengo que correr, pero no parece ser mejor más rápido / más lento, sólo la misma velocidad /.)
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
Cualquier sugerencia sería grande!
Solución
¿Qué hay de:
Campaign.find(30).hits.count
También pudiera considerar agregar el siguiente en hit.rb
(suponiendo una relación de uno a muchos entre campañas y visitas).
belongs_to :campaign, :counter_cache => true
A continuación, necesita una columna de la tabla campaigns
llamada hits_count
. Esto evitará golpear hits
por completo si usted está consiguiendo solamente el conteo.
Puede comprobar el API para el resumen completo.
Otros consejos
Mi ActiveRecord podría ser un poco oxidado, así que perdónenme si es así, pero IIRC Campaign.find(30).hits
es por lo menos dos consultas separadas. ¿Cómo hacer Campaign.find(30, :include => [ :hits ]).hits
? Eso debería realizar una única consulta.