计算平均值时性能不佳
Posted
技术标签:
【中文标题】计算平均值时性能不佳【英文标题】:Poor performance when calculating averages 【发布时间】:2017-07-19 01:27:16 【问题描述】:我需要显示报价的平均值。问题是我必须计算多对多字段组合的平均值。我还得翻页。
我已经做到了。问题是它的性能很差,我正在寻找解决方法。
模型如下所示:
class Offer(models.Model):
price = DecimalField(max_digits=10, decimal_places=2)
quantity = PositiveIntegerField()
product = ForeignKey(Product)
qualifiers = ManyToManyField(Qualifier)
计算平均值的相关代码如下:
def get_average(product, qualifiers, users=None):
offers = Offer.objects.filter(product=product)
if users is not None:
offers = offers.filter(user__in=users)
for qualifier in qualifiers:
offers = offers.filter(qualifiers=qualifier)
if not offers.count():
return None
offers = offers.aggregate(
quantity_x_price_sum=Sum(F('quantity') * F('price'), output_field=FloatField()),
quantity_total=Sum('quantity')
)
# Weighted average
return offers['quantity_x_price_sum'] / offers['quantity_total']
def get_averages(product, limit=20, users=None):
averages = []
colors = product.qualifiers.filter(type=1)
sizes = product.qualifiers.filter(type=2)
other = product.qualifiers.filter(type=3)
qualifiers = [colors, sizes, other]
combinations = itertools.product(*qualifiers)
for combination in combinations:
average = get_average(product, combination, users)
if average is not None:
averages.append(average)
if len(averages) == limit:
return averages
return averages
主要问题在于 itertools.product(*qualifiers)。这可以产生数百种组合。 在 len(prices) == limit 之前,它必须遍历它们中的每一个并执行查询。
欢迎任何帮助。谢谢。
【问题讨论】:
乍一看,您正在创建一个列表 `combinations = list(itertools.product(*qualifiers))` 来获取您的组合,然后将其传递到 for 循环中。对此的改进是创建一个生成器`combinations = itertools.product(*qualifiers)`,然后您可以将组合传递到for循环中。这将减少生成列表然后对其进行迭代的开销。 【参考方案1】:您为什么不自己对查询进行平均聚合?
来自 Django 文档:
# Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
'price__avg': 34.35
https://docs.djangoproject.com/en/1.11/topics/db/aggregation/
编辑:有更复杂的查询方法,希望这会有所帮助。不确定它如何处理非数字数据。
【讨论】:
要添加到这个答案,你应该 - 作为第一步 - 尽可能多地使用 ORM。仅当您无法在 ORM 中完成时,才将所有内容都拉入 Python。这并不总是适用,但它适用于大多数更大/中间的问题。 我需要加权平均值,这与平均值不同 (en.wikipedia.org/wiki/Weighted_arithmetic_mean)。这就是为什么我把这个汇总,做计算。而且我无法直接计算所有报价,我必须为每种产品的每种限定符组合进行计算(然后分页)。我认为这是主要问题。谢谢。以上是关于计算平均值时性能不佳的主要内容,如果未能解决你的问题,请参考以下文章