Migliori prestazioni sulle associazioni
-
21-08-2019 - |
Domanda
In questo momento ho una tabella chiamata campagne che ha molte Hits, se chiamo dire:
Campaign.find(30).hits
che prende 4 secondi, o 4213 ms.
Se io chiamo questo, invece:
campaign = Campaign.find(30) campaign.hits.count
Ha ancora caricare tutti i colpi, poi conta? Oppure è vedere Sto contando ed evita il caricamento di tutti i colpi? (Che è attualmente 300.000+ righe).
Sto cercando di capire un modo intelligente per caricare / contare i miei colpi. Sto pensando di aggiungere un metodo per il mio modello Campaign.rb, come:
def self.total_hits find :first, :select => 'COUNT(id) as hits', :conditions => ["campaign_id = ?", self.id] end
So che query non verrà caricato dal tavolo hits
, ma questo è solo un esempio di contare da un self made interrogazione, apposto su Ruby on Rails facendo per me.
Sarebbe questa query memcache essere più efficiente? (Ho in esecuzione, ma non sembra essere migliore / più veloce / più lento, proprio la stessa velocità.)
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
Tutti i suggerimenti sarebbero grandi!
Soluzione
Come su:
Campaign.find(30).hits.count
Si potrebbe anche considerare l'aggiunta di quanto segue hit.rb
(assumendo una relazione uno-a-molti tra campagne e colpi).
belongs_to :campaign, :counter_cache => true
È quindi necessario una colonna della tabella campaigns
denominata hits_count
. Questo permetterà di evitare di colpire hits
del tutto, se stai ricevendo solo il conteggio.
È possibile controllare il API per la piena riduzione.
Altri suggerimenti
Il mio ActiveRecord potrebbe essere un po 'arrugginito, così mi perdoni se è così, ma IIRC Campaign.find(30).hits
è almeno due query separate. Come si fa Campaign.find(30, :include => [ :hits ]).hits
fare? Questo dovrebbe eseguire una singola query.