Python 在一次数据库命中中评估整个django查询集

Python 在一次数据库命中中评估整个django查询集,python,django,Python,Django,我正在寻找一种方法来评估one数据库命中中的整个django查询集。 我将Django 2.0.8与Python 3.6.5一起使用我曾经评估过列出它们的查询集: queryset = Model.objects.all() # len(connection.queries) = 0 list(queryset) # len(connection.queries) = 87 len(queryset) = 43 只执行了一次数据库命中。但是现在,它似乎对数据库的影响超过了n倍——n是query

我正在寻找一种方法来评估one数据库命中中的整个django查询集。 我将Django 2.0.8与Python 3.6.5一起使用
我曾经评估过列出它们的查询集:

queryset = Model.objects.all()
# len(connection.queries) = 0
list(queryset)
# len(connection.queries) = 87
len(queryset) = 43
只执行了一次数据库命中。但是现在,它似乎对数据库的影响超过了n倍——n是queryset的长度——当n很大并且数据库的影响很大时,这是一个问题。


谢谢你的简短回答:你的假设是错误的。如果对查询集求值,将立即在一个查询中获取所有结果

因此,对于
列表(…)
,您在查询集中进行枚举,Django将首先进行查询,获取该查询的所有记录,然后反序列化所有行,并将其放入列表中

然而,这是一种线性行为,因为答案的大小将随记录数的增加而增加,反序列化答案并将其放入列表的工作量也将随行数的增加而增加

如果您的查询具有与预回迁相关的调用,这也会导致一些额外的查询,但这些查询(查询数)通常会与预回迁次数成线性比例,而不是与记录数成线性比例

如果计划获取大量外键,例如:

for obj in Model.objects.all():
    print(obj.some_reversefk.all())
然后,这将对每个对象进行查询,以获取相关对象(外键指向的对象)

为了避免这种情况,您可以使用
。选择相关(…)
。预回迁相关(…)
.prefetch\u related(..)
将进行一个或两个额外的查询,但将立即获取所有相关对象。因此,您可以使用:

Model.objects.prefetch_related('some_m2m')

事实上,它只在database.read中点击了一次

即使您的模型有相关字段,它也会在单个查询中获取非相关字段。要访问所有相关字段数据,请首先阅读经典的N+1查询问题,阅读


顺便说一句,如果您的模型有太多的对象,请避免在
list()
中使用
.all()
,它将加载内存中的所有对象。改为使用
.count()

这已经用一次点击完成了。您是否有机会“消费”相关对象?我在以前的django版本中就是这样做的,但现在看起来不像了。查看我的编辑您可以查看
连接。查询
?例如,分享最后5个,看看这些是否是相关对象的回迁。@WillemVanOnsem“消费”相关对象是什么意思?你是对的。只有一个查询用于原始模型,其余查询用于相关对象。那么在此之前我应该执行选择相关还是预取相关?@CharlesSiouti:如果是多对一(
ForeignKey
)还是一对一(
OneToOneField
),那么可以使用
select\u-related
,但是对于任何可以作为乘数的东西,都应该使用
prefetch\u-related