ActiveRecord: size vs count

In Rails, è ansible trovare il numero di record utilizzando sia Model.size che Model.count . Se hai a che fare con query più complesse, c’è qualche vantaggio nell’usare un metodo rispetto all’altro? Come sono differenti?

Ad esempio, ho utenti con foto. Se voglio mostrare una tabella di utenti e quante foto hanno, eseguiranno molte istanze di user.photos.size essere più veloce o più lento di user.photos.count ?

Grazie!

Dovresti leggerlo, è ancora valido.

Adatterai la funzione che usi a seconda delle tue esigenze.

Fondamentalmente:

  • se carichi già tutte le voci, ad esempio User.all , dovresti utilizzare la length per evitare un’altra query db

  • se non hai caricato nulla, usa count per fare una query di conteggio sul tuo db

  • se non vuoi preoccuparti di queste considerazioni, usa le size che si adatteranno

Come le altre risposte dichiarano:

  • count eseguirà una query COUNT SQL
  • length calcolerà la lunghezza della matrice risultante
  • size cercheranno di scegliere il più appropriato tra i due per evitare domande eccessive

Ma c’è un’altra cosa. Abbiamo notato un caso in cui le size comportano in modo diverso per count / la length tutto, e ho pensato di condividerlo perché è abbastanza raro da essere trascurato.

  • Se si utilizza a :counter_cache has_many un’associazione has_many , la size utilizzerà direttamente il conteggio memorizzato nella cache e non effettuerà alcuna query aggiuntiva.

     class Image < ActiveRecord::Base belongs_to :product, counter_cache: true end class Product < ActiveRecord::Base has_many :images end > product = Product.first # query, load product into memory > product.images.size # no query, reads the :images_count column > product.images.count # query, SQL COUNT > product.images.length # query, loads images into memory 

Questo comportamento è documentato nelle guide di Rails , ma l’ho perso la prima volta o l’ho dimenticato.

A volte la size “sceglie quella sbagliata” e restituisce un hash (che è ciò che il count farebbe)

In tal caso, utilizza la length per ottenere un numero intero anziché un hash .

Le seguenti strategie fanno tutte una chiamata al database per eseguire una query COUNT(*) .

 Model.count Model.all.size records = Model.all records.count 

Quanto segue non è efficiente in quanto caricherà tutti i record dal database in Ruby, che quindi conta la dimensione della raccolta.

 records = Model.all records.size 

Se i tuoi modelli hanno associazioni e vuoi trovare il numero di oggetti appartenenti (ad es. @customer.orders.size ), puoi evitare le query del database (letture del disco). Usa una cache contatore e Rails manterrà aggiornato il valore della cache e restituirà quel valore in risposta al metodo della size .