ActiveRecord: tamaño vs recuento


En Rails, puede encontrar el número de registros usando Model.size y Model.count. Si está tratando con consultas más complejas, ¿hay alguna ventaja en usar un método sobre el otro? ¿En qué se diferencian?

Por ejemplo, tengo usuarios con fotos. Si quiero mostrar una tabla de usuarios y cuántas fotos tienen, ¿ejecutar muchas instancias de user.photos.size será más rápido o más lento que user.photos.count?

Gracias!

Author: user2262149, 2011-05-21

4 answers

Deberías leer que, sigue siendo válido.

Adaptarás la función que utilices en función de tus necesidades.

Básicamente:

  • Si ya carga todas las entradas, por ejemplo User.all, entonces debe usar length para evitar otra consulta de base de datos

  • Si no tiene nada cargado, use count para hacer una consulta de recuento en su db

  • Si no desea molestarse con estas consideraciones, use size que se adaptará

 294
Author: apneadiving,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-10 22:15:03

Como dicen las otras respuestas:

  • count realizará una consulta SQL COUNT
  • length calculará la longitud de la matriz resultante
  • size intentará elegir el más apropiado de los dos para evitar consultas excesivas

Pero hay una cosa más. Notamos un caso donde size actúa de manera diferente a count/lengthen conjunto, y pensé en compartirlo ya que es lo suficientemente raro como para ser pasado por alto.

  • Si utiliza un :counter_cache en un has_many asociación, size utilizará el recuento en caché directamente, y no hacer una consulta adicional en absoluto.

    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
    

Este comportamiento está documentado en las Guías Rails, pero o lo perdí la primera vez o lo olvidé.

 69
Author: lime,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-09 11:33:17

A veces size "elige el equivocado" y devuelve un hash (que es lo que haría count)

En ese caso, use length para obtener un integer en lugar de hash.

 7
Author: jvalanen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-28 09:32:57

Todas las siguientes estrategias hacen una llamada a la base de datos para realizar una consulta COUNT(*).

Model.count

Model.all.size

records = Model.all
records.count

Lo siguiente no es tan eficiente ya que cargará todos los registros de la base de datos en Ruby, que luego cuenta el tamaño de la colección.

records = Model.all
records.size

Si sus modelos tienen asociaciones y desea encontrar el número de objetos pertenecientes (por ejemplo, @customer.orders.size), puede evitar consultas de base de datos (lecturas de disco). Utilice un contador de caché y Rails mantendrá el valor de caché actualizado y devolverá ese valor en respuesta al método size.

 2
Author: Dennis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-26 19:46:03