[英]Django: prefetch_related has no effect
我正在嘗試使用prefetch_related
優化數據庫查詢,但沒有成功。
class Order(models.Model):
# some fields ...
@property
def last_operation(self) -> Optional['OrderOperation']:
try:
return self.orderoperation_set.latest()
except OrderOperation.DoesNotExist:
return None
@property
def total(self) -> Optional[Decimal]:
last_operation = self.last_operation
return last_operation.total if last_operation else None
class OrderOperation(TimeStampable, models.Model):
order = models.ForeignKey(Order)
total = DecimalField(max_digits=9, decimal_places=2)
orders = Order.objects.prefetch_related('orderoperation_set') # There are 1000 orders
result = sum([order.total for order in orders])
len(connection.queries)
>>> 1003
如我們所見,每個order.total
有一個查詢,所以有1000個查詢,這使整個請求非常糟糕,性能與訂單數成線性關系。
為了理解為什么會這樣,我在prefetch_related Django doc中找到了這個:
請記住,與QuerySet一樣,任何暗示不同數據庫查詢的后續鏈接方法都將忽略先前緩存的結果,並使用新的數據庫查詢來檢索數據。
因此,每次調用latest()
運行一個新查詢似乎很正常。
在這種情況下,您將如何提高性能? (進行一些查詢而不是N,其中N是訂單數)。
由於OrderOperation僅包含單個相關字段total
,因此更好的方法是使用子查詢來注釋原始查詢中最新操作的總數:
from django.db.models import OuterRef, Subquery
newest = OrderOperation.objects.filter(post=OuterRef('pk')).order_by('-created_at') # or whatever the timestamp field is
orders = Order.objects.annotate(newest_operation_total=Subquery(newest.values('total')[:1]))
我在這里發布答案,你能告訴我這是否有意義嗎?
而不是調用的latest()
如果我只是得到第一個項目在我的查詢集有[0]
或最后用len(qs)-1
,假設order_operations已經訂購?
@property
def last_operation(self) -> Optional['OrderOperation']:
try:
qs = self.orderoperation_set.all()
return qs[len(qs) - 1]
except IndexError:
return None
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.