我正在评估一个QuerySet,然后是另一个,但第二个是第一个的子集。我正在尝试以有效的方式执行此操作,尽可能少的数据库调用。 (之前有人问过,但说实话,我并不完全理解答案,我不确定它们是否完全适用于我正在考虑的事情。)
在视图中使用Django doc example Weblog models,这是尝试优化之前的代码:
myblog = Blog.objects.get(pk=1)
d={} #going to pass this to my template
# not using count()
d['num_of_entries'] = len(myblog.entry_set.all())
# not using exists()
d['is_jolly'] = bool(Entry.objects.filter(blog=myblog, headline__startswith='Jolly'))
# ... other code but no further use of database in this view
第二个QuerySet是第一个QuerySet的子集。我是否应该尝试使用纯Python来获取子集(因此只评估一个QuerySet - 一个较少的数据库调用)?
或者,或许只是做以下事情?
# other code as above
d['num_of_entries'] = myblog.entry_set.count()
d['is_jolly'] = Entry.objects.filter(blog=myblog, headline__startswith='Jolly').exists()
# ... other code but no further use of database in this view
答案 0 :(得分:5)
“尽可能少的数据库查询”不是正确的标准。您还要考虑这些数据库查询完成的工作量,以及从数据库传输到Django服务器的数据量。
让我们考虑实现你所追求的两种方式。方法1:
entries = myblog.entry_set.all()
num_of_entries = len(entries)
is_jolly = any(e.headline.startswith('Jolly') for e in entries)
方法2:
num_of_entries = myblog.entry_set.count()
is_jolly = Entry.objects.filter(blog=myblog, headline__startswith='Jolly').exists()
在方法1中,有一个数据库查询,但该查询类似于SELECT * FROM ENTRY WHERE ...
。它可能会获取大量条目,并将所有内容通过网络传输到您的Django服务器,然后将几乎所有内容丢弃(实际上它唯一的字段)看看是headline
字段。
在方法2中有两个数据库查询,但第一个是SELECT COUNT(*) FROM ENTRY WHERE ...
,它只获取一个整数,第二个是SELECT EXISTS(...)
,它只获取一个布尔值。由于这些查询不必获取所有匹配的条目,因此数据库可以更多地优化查询。
因此,在这种情况下,方法2看起来要好得多,即使它会发出更多查询。