Rails ActiveRecord: count, length or size?

The object oriented database layer “ActiveRecord” offeres three different methods to determine the number of objects: count(), length() und size().

Alle drei Methoden liefern das gleiche Ergebnis. Was nehmen wir wann? Warum ist es überhaupt wichtig? Nimmt man die falsche Methode, dann erzeugt unsere Ruby-on-Rails-Anwendung überflüssige Datenbankabfragen oder braucht mehr Speicher als eigentlich nötig. Die Anwendung skaliert dann schlechter. Um mir die Unterschiede zwischen den Methoden leichter zu merken habe ich folgendes Schema erstellt.

count: das lese ich als Befehl.
Der Befehl wird an die Datenbank weitergegeben, die Datenbank führt dann select count(*) from ... aus.

Diese Methode ist perfekt wenn wir wirklich nur die Anzahl wissen wollen: Es werden keine überflüssigen Daten von der Datenbank zur Anwendung geschickt, sondern nur die Anzahl zurückgegeben. Die Datenbank ist bei dieser Art von Anfragen meist auch schneller, weil sie die Anfrage nur aus ihren Index beantworten kann.

Wenn die Daten aber schon in unserer Anwendung verfügbar sind, wird trotzdem ein Datenbankaufruf abgesetzt.

length: eine physikalische Eigenschaft.

Die length()-Methode liefert die Länge des Arrays (bzw. der Assoziation oder der Relation).

Wenn die Daten schon im Speicher sind, wird die Datenbank nicht gefragt. Wir haben dann eine Datenbankanfrage gespart.

Beispiel: wir zeigen in der View eine Tabelle mit unseren Daten, und darunter die Anzahl der Elemente. Die Daten mussten wir sowieso schon aus der Datenbank laden, deshalb wäre es Unsinn die Datenbank nochmal nach der Anzahl zu fragen.

Wenn die Daten noch nicht in unseren Speicher sind, schlägt die Magie von ActiveRecord zu. Das Array wird befüllt (populated). Dazu wird die Datenbank nach allen Werten der betreffenden Objekte gefragt. Die Objekte werden komplett aufgebaut, mit allen Attributen, um dann durchgezählt zu werden.

Wenn wir nur die Anzahl wissen wollen ist das natürlich unnötig. Dann ist count() besser.

Wenn wir die Daten aber sowieso gleich brauchen ist das genau richtig.

size: die abstraktere Version von length.

Wenn Daten schon da sind, ruft die size() Methode intern length() auf. Wenn die Daten noch nicht da sind, ruft size() intern stattdessen die count()-Methode auf. Das klingt wie die perfekte Mischung.

In einem Fall ist size() Methode trotzdem eine schlechte Wahl: Wenn wir die Daten kurz danach doch noch brauchen, haben wir einen überflüssigen “select count“-Datenbankaufruf erzeugt.

Leave a comment