这来自django docs on the queryset iterator()
method:
QuerySet通常在内部缓存其结果,以便重复进行评估 不要导致其他查询。相反,iterator()将读取结果 直接,不在QuerySet级别进行任何缓存(在内部,默认迭代器调用iterator()并缓存返回值)。对于QuerySet来说 返回大量只需要访问一次的对象, 这可以带来更好的性能和显着的内存减少。
阅读之后,我仍然感到困惑:关于性能提升和内存减少的一线表明我们应该使用iterator()
方法。有人可以提供一些好的和坏的案例iterator()
用法的例子吗?
即使查询结果没有被缓存,如果他们真的想多次访问模型,也不能有人只是执行以下操作?
saved_queries = list(Model.objects.all().iterator())
答案 0 :(得分:27)
请注意您调用的句子的第一部分:
For a QuerySet which returns a large number of objects that you only need to access once
所以反过来说:如果你需要重复使用一组结果,并且它们不是那么多,以至于导致内存问题,那么你就不应该使用iterator
。因为额外的数据库往返总是会降低您的性能而不是使用缓存的结果。
您可以强制将QuerySet计算到列表中,但是:
saved_queries = Model.objects.all()
QuerySet
s are lazy,因此您可以拥有一个上下文处理器,例如,将QuerySet放入每个请求的上下文中,但只有在您访问某些请求时才会对其进行评估,但是您是否强制评估该数据库每次请求都会发生命中典型的Web应用程序案例适用于相对较小的结果集(必须及时将它们传送到浏览器,因此如果需要,可以采用分页或类似技术来减少数据量)所以通常标准{{ 1}}行为就是你想要的。毫无疑问,您必须store the QuerySet in a variable才能获得缓存的好处。
充分利用迭代器:处理大量可用内存的处理结果(大量小对象或较少的大对象)。根据我的经验,这通常是在进行大量数据处理时的管理命令。
答案 1 :(得分:0)
我同意史蒂文的意见,我希望得到一个观察结果:
“它需要更多的输入而不仅仅是saved_queries = Model.objects.all()”。是的,但是为什么你应该使用list(Model.objcts.all())有一个重大的区别。让我举个例子,如果你将分配给变量,它将执行查询而不是保存在那里,让我们假设你有+ 1M记录,这意味着你将在列表中有+ 1M记录你可能会或者可能不会立即使用,所以我建议只使用Steven说,只使用 Model.objects.all(),因为这分配给一个变量,它将不会执行,直到你调用变量,节省数据库调用。
您应该使用prefetch_related()来避免对数据库进行多次调用,因此,它将使用django反向查找来帮助您并节省大量时间。