slothis · Deutsch

Django Performance: count() vs. len() bei QuerySets

2020-12-05 · Aktualisiert: 2026-08-11 · Original (Koreanisch)

Dieser Artikel wurde mit KI-Unterstützung aus dem koreanischen Original übersetzt. Das koreanische Original lesen →
Offizielles Logo des Django-Frameworks in weißen Kleinbuchstaben auf dunkelgrünem Hintergrund

Kürzlich bekam ich bei einem Code-Review den Kommentar, ich solle doch count verwenden, anstatt die Zeilen mit len() zu zählen. Da ich noch ein Anfänger in Sachen ORM und Django bin, habe ich ein wenig auf Stackoverflow recherchiert. Dort empfehlen eigentlich alle, für das Zählen von Zeilen möglichst count zu nutzen. Schauen wir uns mal an, warum das so ist.

Nehmen wir an, wir wollen die Anzahl der User in unserem aktuellen Service herausfinden.

(Vorsicht: Wenn man das in einem System mit Millionen von Usern einfach mal so aus Spaß macht, wird man schnell von den DevOps-Jungs der Firma zum Rapport gerufen.)

qs = User.objects.all()

# Methode mit count() des QuerySets
def user_count_by_count():
    return qs.count()

# Methode mit len()
def user_count_by_len():
    return len(qs)

Bei count() wird SELECT COUNT(*) FROM User im RDBMS ausgeführt und nur der Zählwert an Python übergeben.

Bei len() wird hingegen SELECT * FROM User im RDBMS ausgeführt, das komplette Ergebnis an Python übergeben und erst dann mit len() gezählt.

Es heißt oft: Wenn du Zeilen zählen musst, nutze count(). Der Grund dafür ist, dass beim Versuch, count durch len() zu ersetzen, das Fetchen O(N) Zeit in Anspruch nimmt. Außerdem wird das Ergebnis in den Arbeitsspeicher des Webservers geladen, was O(N) Speicherplatz kostet, und durch die Kopierzeit entsteht zusätzlich O(N) beim Zeitaufwand. Obendrauf kommt noch die Ausführungszeit von len() selbst. Diese beiden Prozesse hängen natürlich von der Infrastruktur ab, aber man sagt, dass count etwa doppelt so schnell ist.

Es gibt jedoch Fälle, in denen len() vorteilhafter ist als count.

qs = User.objects.all()

def prefer_len_to_count():
    # Angenommen, es gibt ein telephone-Feld in den User-Infos, und wir sammeln diese in einer Liste.
    telephones = [p.telephone for p in qs]
    # Dann machen wir irgendwas mit diesen Infos...
    ...
    # Und holen uns die Anzahl von qs (den Verwendungszweck könnt ihr euch selbst ausdenken)
    len(qs)

Wenn man das QuerySet wie oben ohnehin fetchen und verwenden muss, ist len ein kleines bisschen im Vorteil. Der Grund ist, dass man bei count() zweimal auf das RDBMS zugreifen müsste (einmal für den Fetch, einmal für count()).

Auch wenn ich dafür vielleicht Ärger von den DevOps-Jungs bekomme: Solange man nicht extrem viele (was "viele" sind, hängt stark von der Infrastruktur ab) Zeilen zählen muss, kann man bedenkenlos einfach count verwenden.

Natürlich wird die Verwendung von count auch in Templates empfohlen.

Das folgende count

{{ some_queryset.count }}

wird eher empfohlen als das folgende len.

{{ len(some_queryset) }}

Quelle: stackoverflow.com/questions/14327036/count-vs-len-on-a-django-queryset


#django #django