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/pass
  • qs.count() 144.33 usec/pass
  • qs[0]: 324.98 usec/pass

On MySQL, 57 rows:

  • bare qs: 1.07 usec/pass
  • qs.exists(): 1.21 usec/pass
  • qs.count(): 1.16 usec/pass
  • qs[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)
Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐