it-swarm.com.de

ActiveRecord: Größe vs. Anzahl

In Rails können Sie die Anzahl der Datensätze mit Model.size und Model.count. Wenn Sie sich mit komplexeren Abfragen beschäftigen, hat die Verwendung einer Methode gegenüber der anderen einen Vorteil? Wie unterscheiden sie sich?

Zum Beispiel habe ich Benutzer mit Fotos. Wenn ich eine Tabelle mit Benutzern anzeigen möchte und wie viele Fotos sie haben, werden viele Instanzen von user.photos.size schneller oder langsamer als user.photos.count?

Vielen Dank!

189
Andrew

Sie sollten lesen dass , es ist immer noch gültig.

Sie werden die von Ihnen verwendete Funktion an Ihre Bedürfnisse anpassen.

Grundsätzlich gilt:

  • wenn Sie bereits alle Einträge geladen haben, sagen Sie User.all, dann sollten Sie length verwenden, um eine weitere Datenbankabfrage zu vermeiden

  • wenn Sie noch nichts geladen haben, verwenden Sie count, um eine Count-Abfrage für Ihre Datenbank durchzuführen

  • wenn Sie sich nicht mit diesen Überlegungen befassen möchten, verwenden Sie size, das sich anpasst

326
apneadiving

In den anderen Antworten heißt es:

  • count führt eine SQL COUNT Abfrage durch
  • length berechnet die Länge des resultierenden Arrays
  • size wird versuchen, die am besten geeignete der beiden auszuwählen, um übermäßige Abfragen zu vermeiden

Aber da ist noch eine Sache. Wir haben einen Fall bemerkt, in dem sich size anders verhält als count/length, und ich dachte, ich würde es teilen, da es selten genug ist, um übersehen zu werden.

  • Wenn Sie ein :counter_cache auf einen has_many Assoziation, size verwendet die zwischengespeicherte Anzahl direkt und führt überhaupt keine zusätzliche Abfrage durch.

    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
    

Dieses Verhalten ist in Rails Guides dokumentiert, aber ich habe es entweder beim ersten Mal verpasst oder vergessen.

79
lime

Manchmal wählt size "das falsche aus" und gibt ein Hash zurück (was count tun würde)

In diesem Fall verwenden Sie length, um eine Ganzzahl anstelle von Hash zu erhalten.

7
jvalanen

Die folgenden Strategien rufen alle die Datenbank auf, um eine COUNT(*)-Abfrage auszuführen.

Model.count

Model.all.size

records = Model.all
records.count

Das Folgende ist nicht so effizient, da alle Datensätze aus der Datenbank in Ruby geladen werden, was dann die Größe der Sammlung zählt.

records = Model.all
records.size

Wenn Ihre Modelle Assoziationen aufweisen und Sie die Anzahl zugehöriger Objekte ermitteln möchten (z. B. @customer.orders.size) können Sie Datenbankabfragen (Festplattenlesevorgänge) vermeiden. Verwenden Sie ein Zähler-Cache und Rails aktualisiert den Cache-Wert und gibt diesen Wert als Antwort auf die Methode size zurück.

3
Dennis

Ich habe empfohlen, die Größenfunktion zu verwenden.

class Customer < ActiveRecord::Base
  has_many :customer_activities
end

class CustomerActivity < ActiveRecord::Base
  belongs_to :customer, counter_cache: true
end

Betrachten Sie diese beiden Modelle. Der Kunde hat viele Kundenaktivitäten.

Wenn Sie einen: counter_cache für eine has_many-Zuordnung verwenden, verwendet size die zwischengespeicherte Anzahl direkt und führt überhaupt keine zusätzliche Abfrage durch.

Stellen Sie sich ein Beispiel vor: In meiner Datenbank hat ein Kunde 20.000 Kundenaktivitäten, und ich versuche, die Anzahl der Datensätze der Kundenaktivitäten dieses Kunden mit den Methoden count, length und size zu zählen. Hier unten der Benchmark-Bericht aller dieser Methoden.

            user     system      total        real
Count:     0.000000   0.000000   0.000000 (  0.006105)
Size:      0.010000   0.000000   0.010000 (  0.003797)
Length:    0.030000   0.000000   0.030000 (  0.026481)

daher habe ich festgestellt, dass die Verwendung von: counter_cache Size die beste Option ist, um die Anzahl der Datensätze zu berechnen.

1

tl; dr

  • Wenn Sie wissen, dass Sie die Daten nicht benötigen, verwenden Sie count.
  • Wenn Sie wissen, dass Sie die Daten verwenden oder verwendet haben, verwenden Sie length.
  • Wenn Sie nicht wissen, was Sie tun, verwenden Sie size...

anzahl

Beschließt, eine Select count(*)... - Abfrage an die Datenbank zu senden. Der Weg, wenn Sie nicht die Daten, sondern nur die Anzahl benötigen.

Beispiel: Anzahl der neuen Nachrichten, Gesamtzahl der Elemente, wenn nur eine Seite angezeigt werden soll usw.

länge

Lädt die erforderlichen Daten, d. H. Die Abfrage nach Bedarf, und zählt sie dann nur. Der Weg zu gehen, wenn Sie die Daten verwenden.

Beispiel: Zusammenfassung einer vollständig geladenen Tabelle, Titel der angezeigten Daten usw.

größe

Es prüft, ob die Daten geladen wurden (d. H. Bereits in Rails), zählt sie dann einfach, andernfalls ruft es count auf. (plus die Fallstricke, die bereits in anderen Einträgen erwähnt wurden).

def size
  loaded? ? @records.length : count(:all)
end

Was ist das Problem?

Möglicherweise treffen Sie die Datenbank zweimal, wenn Sie dies nicht in der richtigen Reihenfolge tun (z. B. wenn Sie die Anzahl der Elemente in einer Tabelle über der gerenderten Tabelle rendern, werden effektiv zwei Aufrufe an die Datenbank gesendet).

0
estani