我有以下课程:
class Instance(models.Model):
products = models.ManyToManyField(Product, blank=True)
class Product(models.Model):
description = HTMLField(blank=True, null=True)
short_description = HTMLField(blank=True, null=True)
这是我用来更新实例的表格
class InstanceModelForm(InstanceValidatorMixin, UpdateInstanceLastUpdatedMixin, forms.ModelForm):
class Meta:
model = Instance
products = forms.ModelMultipleChoiceField(required=False, queryset=Product.objects.annotate(i_count=Count('instance')).order_by('i_count'))
我的instance-product表相当大(〜1000行),并且自从我添加了产品的查询集以来,我看到由于heroku的30秒请求限制而导致Web请求超时。
我有以下见解:
精度对我而言并不重要-不一定必须非常准确。是的,我想按产品链接到的实例数对产品进行排序,但是如果偏离5或10,则没关系 那么多。
有限数量的产品-当我的用户选择要链接到实例的产品时,他们主要对与实例的总链接少于10个的产品感兴趣。我不知道部分查询是否准确,但是如果可能的话,我愿意尝试。
工作量-我知道可以安装一些框架来缓存很多东西。我正在寻找重量轻且需要不到1个小时才能启动并运行的东西。
答案 0 :(得分:1)
首先,我想确保性能问题实际上来自查询。我试图重现您的问题:
>>> Instance.objects.count()
102499
>>> Product.objects.count()
1000
>>> sum(p.instance_set.count() for p in Product.objects.all())/Product.objects.count()
273.084
>>> list(Product.objects.annotate(i_count=Count('instance')).order_by('i_count'))
[...]
>>> from django.db import connection
>>> connection.queries[-1]
{'sql': 'SELECT "products_product"."id", "products_product"."description", "products_product"."short_description", COUNT("products_instance_products"."instance_id") AS "i_count" FROM "products_product" LEFT OUTER JOIN "products_instance_products" ON ("products_product"."id" = "products_instance_products"."product_id") GROUP BY "products_product"."id", "products_product"."description", "products_product"."short_description" ORDER BY "i_count" ASC', 'time': '0.189'}
偶然地,我创建了一个可能比您大得多的数据集。如您所见,我有1000个产品,平均约有273个相关实例,但是查询仍然不到一秒钟(在SQLite和PostgreSQL上)。
对heroku run bash
使用一次性测功机,并检查是否获得相同的数字。
我的猜测是您的性能问题是由
引起的Product
都会进行一个额外的查询,例如在您的Product.__str__
方法中。MultipleChoiceField
字段的实际呈现。默认情况下,它将呈现为<select>
,每个<option>
的{{1}}。这可能很慢,即使不是那样,使用起来也很不方便。您可能想要使用其他小部件,例如Product
。