In Django, what is the most efficient way to check for an empty query set?
Answer a question
I've heard suggestions to use the following:
if qs.exists():
...
if qs.count():
...
try:
qs[0]
except IndexError:
...
Copied from comment below: "I'm looking for a statement like "In MySQL and PostgreSQL count() is faster for short queries, exists() is faster for long queries, and use QuerySet[0] when it's likely that you're going to need the first element and you want to check that it exists. However, when count() is faster it's only marginally faster so it's advisable to always use exists() when choosing between the two."
Answers
exists() is generally faster than count(), though not always (see test below). count() can be used to check for both existence and length.
Only use qs[0]
if you actually need the object. It's significantly slower if you're just testing for existence.
On Amazon SimpleDB, 400,000 rows:
- bare
qs
: 325.00 usec/pass qs.exists()
: 144.46 usec/passqs.count()
144.33 usec/passqs[0]
: 324.98 usec/pass
On MySQL, 57 rows:
- bare
qs
: 1.07 usec/pass qs.exists()
: 1.21 usec/passqs.count()
: 1.16 usec/passqs[0]
: 1.27 usec/pass
I used a random query for each pass to reduce the risk of db-level caching. Test code:
import timeit
base = """
import random
from plum.bacon.models import Session
ip_addr = str(random.randint(0,256))+'.'+str(random.randint(0,256))+'.'+str(random.randint(0,256))+'.'+str(random.randint(0,256))
try:
session = Session.objects.filter(ip=ip_addr)%s
if session:
pass
except:
pass
"""
query_variatons = [
base % "",
base % ".exists()",
base % ".count()",
base % "[0]"
]
for s in query_variatons:
t = timeit.Timer(stmt=s)
print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100000)
更多推荐
所有评论(0)