何时使用或不使用django ORM中的iterator()

时间:2012-10-01 21:52:13

标签: python django orm iterator django-queryset

这来自django docs on the queryset iterator() method

  

QuerySet通常在内部缓存其结果,以便重复进行评估       不要导致其他查询。相反,iterator()将读取结果       直接,不在QuerySet级别进行任何缓存(在内部,默认迭代器调用iterator()并缓存返回值)。对于QuerySet来说       返回大量只需要访问一次的对象,       这可以带来更好的性能和显着的内存减少。

阅读之后,我仍然感到困惑:关于性能提升和内存减少的一线表明我们应该使用iterator()方法。有人可以提供一些好的和坏的案例iterator()用法的例子吗?

即使查询结果没有被缓存,如果他们真的想多次访问模型,也不能有人只是执行以下操作?

saved_queries = list(Model.objects.all().iterator())

2 个答案:

答案 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()
  • 说你在网页上分页结果:你会强制所有结果进入内存(回到可能的内存问题)而不是让后续的分页器选择它需要的20个结果的切片
  • QuerySets 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反向查找来帮助您并节省大量时间。