回答

收藏

在Django中,检查空查询集的最有效方法是什么?

技术问答 技术问答 234 人阅读 | 0 人回复 | 2023-09-14

我听说过使用以下方法的建议:* O# p' K  v; u- H1 j1 F; R
if qs.exists():" F) ^3 T3 O. w
    ...( p0 s' o9 }( H) n
if qs.count():
, p8 {4 w- J# L, o    ...
- |: {) \, q6 v& c: E$ L5 D- ~try:
4 ]6 Q( e# T5 w7 E5 [2 }9 R3 R    qs[0]
& w) f- a8 f1 X" I. P: Wexcept IndexError:* q7 r3 s" K/ c$ a
    ...' s+ z% Z) d" i& W" x& N
从下面的评论中复制:“我正在寻找这样的语句:在MySQL和PostgreSQL中,对于短查询,count()更快,对于长查询,exist(()更快,并且在可能的情况下使用QuerySet
. h3 P( K) I$ `. r, r6 i( {[0]将需要第一个元素,并且您要检查它是否存在。但是,当count()更快时,它仅略微更快,因此建议在两者之间进行选择时始终使用exist()。”
8 m. ~) @* \5 D) [8 ]6 c                / [- X6 B) I" `  Q" ?; a
解决方案:& r; l! t8 V$ Y8 _  I
               
: u9 F, R% ?6 R5 r: ?& C# K$ w/ t+ M7 }1 j2 f+ I
& I5 U; l! U7 m5 E+ ^$ P0 ]! ^+ V
                exist()通常比count()更快,尽管并非总是如此(请参见下面的测试)。count()可用于检查存在性和长度。
& b) ?( I6 c3 S* Q6 z+ M仅qs[0]在确实需要该对象时使用。如果您仅测试存在性,则速度会明显变慢。
0 K& O$ J6 R% H$ ~) Q8 e在Amazon SimpleDB上,400,000行:
: b4 o; Y0 y  \/ E2 \# w裸机qs:325.00 usec / pass' ?# r  ?! W# x: n+ ]
qs.exists():144.46 usec / pass
$ k7 \' q% e4 T; n) mqs.count() 144.33 usec / pass
2 P3 |4 {7 f4 j, i/ p' v$ Sqs[0]:324.98 usec / pass
+ N5 M( s. W) c; _1 a0 _$ B9 \

3 a' t' T( U6 Y8 {在MySQL上,有57行:
/ I  q9 l4 i. ^8 \. B% \裸qs:1.07 usec / pass
" v' h* ?4 ~7 y- b  X4 Zqs.exists():1.21 usc / pass* j) h6 F. L# }
qs.count():1.16 usec / pass  m) r& S! E6 Q( y9 [
qs[0]:1.27微秒/通过" V4 v7 I3 _" s  T! t: |
4 h! s+ \3 [9 H# ?, d
我对每个通道使用了随机查询,以降低数据库级缓存的风险。测试代码:
% |7 ~; q8 `6 Z/ a& x- `import timeit& Q" i. Z- i- T: J8 k& V- L
base = """8 F# j9 Z$ o2 |0 z
import random. Q* ~5 K7 b8 n4 {- A) g
from plum.bacon.models import Session2 W  b$ N( G# X, N* L- e, J" ?9 O
ip_addr = str(random.randint(0,256))+'.'+str(random.randint(0,256))+'.'+str(random.randint(0,256))+'.'+str(random.randint(0,256))) A) e9 D' o2 n7 q3 M& X$ w
try:: Q/ r  o" t# ?# b, A1 U( a% i( d
    session = Session.objects.filter(ip=ip_addr)%s
8 ~# {4 q2 E" t3 ^    if session:
& n0 ?* f  L* K/ i3 S* ~' k% W        pass
  l' y6 ]% |/ z9 e. v1 @except:' ~2 s6 ?2 ^5 m& |1 @/ L
    pass( w2 ^) K- V1 A: @# S
"""
# m+ I$ N! Y, I2 z8 v( b/ equery_variatons = [
# c; p' Y7 ]% j% g    base % "",
; Q; h. S+ h9 f$ j6 w* K4 |' @    base  % ".exists()",) U5 |6 m) O9 o& X" ^
    base  % ".count()",! X7 A, V7 a) }7 H% ?% S0 b
    base  % "[0]"
; i# W( c) w  k    ]& r- U: m( C: Q9 h: X9 I" b
for s in query_variatons:/ F: i; o6 i5 ~! W; B8 _& d. ~! {
    t = timeit.Timer(stmt=s)9 q' c% c$ O, A5 Z7 r/ J
    print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100000)
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则