Opened 17 years ago

Closed 17 years ago

#4739 closed (wontfix)

len(queryset) is slow

Reported by: tclugg@… Owned by: Adrian Holovaty
Component: Database layer (models, ORM) Version: dev
Severity: Keywords: queryset, len, count, select
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

len(queryset) uses queryset.iterator, which performs SQL SELECT instead of SQL COUNT. queryset.len should instead call queryset.count() which is much faster as it will use the cached result of SELECT if available, otherwise performing a SQL COUNT.

Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py (revision 5583)
+++ django/db/models/query.py (working copy)
@@ -106,7 +106,7 @@

return repr(self._get_data())

def len(self):

  • return len(self._get_data())

+ return self.count()

def iter(self):

return iter(self._get_data())

Change History (2)

comment:1 by tclugg@…, 17 years ago

The patch again wrapped in a code block:

Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py   (revision 5583)
+++ django/db/models/query.py   (working copy)
@@ -106,7 +106,7 @@
         return repr(self._get_data())

     def __len__(self):
-        return len(self._get_data())
+        return self.count()

     def __iter__(self):
         return iter(self._get_data())

comment:2 by Malcolm Tredinnick, 17 years ago

Resolution: wontfix
Status: newclosed

Your solution requires a second database query, which isn't so great.

If a user only wants the size of a set of results, they can call count() explicitly. If they are calling len() on the queryset, then they've already created the queryset for other reasons, so actually using the results we've already queried is efficient (recalling that the queryset is going to cache the results anyway).

All that being said, one enhancement that will be introduced soon is to speed up len() for most database backends by using the cursor's rowcount attribute and (only if that isn't implemented) then falling back to the size of the result set.

So, yes, we can make len() slightly more efficient for most database backends (not SQLite, but life's like that sometimes), but it isn't going to be by making another database call.

Note: See TracTickets for help on using tickets.
Back to Top