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

Luc*_*ang 20 python django orm iterator django-queryset

这是来自queryset iterator()方法django文档:

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

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

即使查询结果没有被缓存,如果他们真的想多次访问模型,有人只能做以下事情吗?

saved_queries = list(Model.objects.all().iterator())
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 29

请注意您调用的句子的第一部分: 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是懒惰的,所以你可以有一个上下文处理器,例如,它将QuerySet放入每个请求的上下文中,但只在你在某些请求上访问它时才会被评估,但如果你强迫评估每次请求都会发生数据库命中

典型的Web应用程序案例适用于相对较小的结果集(它们必须及时交付给浏览器,因此如果需要,可以采用分页或类似技术来减少数据量)因此通常标准QuerySet行为就是您想要的.毫无疑问,您必须将QuerySet存储在变量中以获得缓存的好处.

好好利用迭代器:处理大量可用内存的处理结果(大量小对象或较少的大对象).根据我的经验,这通常是在进行大量数据处理时的管理命令.


小智 7

我同意史蒂文的观点,我想发表一下看法:

  • “它需要更多的输入,而不仅仅是 saving_queries = Model.objects.all()”。是的,但是有一个主要区别,为什么你应该使用 list(Model.objects.all())。让我给你举个例子,如果你把分配给一个变量,它将执行查询并将其保存在那里,让我们假设你有+1M记录,所以这意味着,你将在列表中拥有+1M记录您可能会或可能不会立即使用,所以我建议只使用史蒂文所说的,仅使用Model.objects.all(),因为这分配给一个变量,它不会执行,直到您调用该变量,从而节省您的数据库来电。

  • 您应该使用 prefetch_lated() 来避免对数据库进行过多的调用,因此,它将使用 Django 反向查找来帮助您并节省大量时间。