【发布时间】:2021-04-23 11:02:01
【问题描述】:
我遇到了 Django 查询的性能问题。 假设我有 3 个模型,并且 Company 表中有 100 行:
from django.db import models
class Company(models.Model):
name = models.CharField()
def order_count(self):
return self.orders.count()
def order_sum(self):
return (self.orders.all().aggregate(models.Sum('total')))['total__sum']
class Customer(models.Model):
company = models.ForeignKey(Company, related_name="customer", on_delete=models.PROTECT)
name = models.CharField()
def order_count(self):
return self.orders.count()
class Order(models.Model):
company = models.ForeignKey(Company, related_name='orders')
customer = models.ForeignKey(Customer, related_name="orders")
value = models.FloatField()
我希望我的模板显示公司名称及其订单总和,然后对于该公司的每个客户,我想显示客户名称及其订单数量。
我在views.py 中的查询代码正在使用这样的预取:
queryset = Company.objects.prefetch_related(
models.Prefetch('customer',
queryset=Customer.objects.prefetch_related('orders')), 'orders')
template 的伪代码:
for company in queryset:
print(company.name, company.order_count, company.order_sum)
for customer in company:
print(customer.name, customer.order_count)
我用 Django 调试工具栏检查过,它需要 105 次查询,带有这些 SQL 语句(伪代码):
SELECT * FROM company
SELECT * FROM customer WHERE customer.company_id IN (100 IDs of the companies)
SELECT * FROM order WHERE order.customer_id IN (the IDs from previous command)(this duplicates 2 times)
SELECT * FROM order WHERE order.company_id IN (100 IDs of the companies)
SELECT SUM(order.value) FROM order WHERE order.company_id = %s (this duplicates 100 times, for each company's id)
正如 Django 调试工具栏 (DjDT) 向我展示的那样:
- 前 5 个查询在我评估查询集时出现(模板中的 for 循环)
- 当我请求 order_sum() 时,接下来的 100 个查询会出现(模板中的第 2 行) 有了这个,DjDT 告诉我它大约需要 700-800 毫秒(模板中的一些过程但似乎花费的时间并不多,我测试过)。我想把它减少到 500 毫秒。
所以我的问题是:
- 我可以做些什么来改进?
- 为什么第三个 SQL 查询重复了 2 次。
- 有没有办法将最后一个 SQL 查询减少到只有 1 个查询?
我是新手所以请帮助^^。
#非常感谢您的宝贵时间^^
【问题讨论】:
标签: python sql django performance sqlite