3

哪一个对性能更好?

我们拿一片产品。这使我们无法批量更新。

products = Product.objects.filter(featured=True).order_by("-modified_on")[3:]

for product in products:
  product.featured = False
  product.save()

或(无效)

for product in products.iterator():
  product.update(featured=False)

我也尝试过 QuerySet 的 in 语句,如下所示。

Product.objects.filter(pk__in=products).update(featured=False)

这条线在 SQLite 上运行良好。但是,它在 MySQL 异常之后上升。所以,我不能用那个。

DatabaseError: (1235, "这个版本的 MySQL 还不支持 'LIMIT & IN/ALL/ANY/SOME 子查询'")

编辑: iterator() 方法也会导致重新评估查询。因此,这对性能不利。

4

2 回答 2

2

正如@Chris Pratt 在评论中指出的那样,第二个示例无效,因为对象没有更新方法。您的第一个示例将需要等于 results+1 的查询,因为它必须更新每个对象。如果你有 1000 种产品,那可能真的很昂贵。理想情况下,如果可能,您确实希望将其减少到更固定的费用。

这与另一个问题的情况类似:
Django: Cannot update a query once a slice has been taken

话虽如此,您必须至少在 2 个查询中执行此操作,但您必须对如何构建 LIMIT 有点偷偷摸摸......

使用Q 对象进行复杂查询

# get the IDs we want to exclude
products = Product.objects.filter(featured=True).order_by("-modified_on")[:3]
# flatten them into just a list of ids
ids = products.values_list('id', flat=True)

# Now use the Q object to construct a complex query
from django.db.models import Q
# This builds a list of "AND id NOT EQUAL TO i"
limits = [~Q(id=i) for i in ids]
Product.objects.filter(featured=True, *limits).update(featured=False)
于 2012-05-21T19:57:36.970 回答
0

在某些情况下,将 QuerySet 缓存在数组中是可以接受的

products = list(products)
Product.objects.filter(pk__in=products).update(featured=False)

使用values_list 进行小优化

products_id = list(products.values_list('id', flat=True)
Product.objects.filter(pk__in=products_id).update(featured=False)
于 2015-02-05T03:55:11.700 回答