Django-改进M2M过滤中__in查询集的性能 [英] django - improve performance of __in queryset in M2M filtering
本文介绍了Django-改进M2M过滤中__in查询集的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个与另一个模型具有M2M关系的模型。
这些是我的型号:
class Catalogue(models.Model):
city = models.CharField(db_index=True,max_length=100, null=True)
district = models.CharField(db_index=True,max_length=100, null=True)
type = models.ManyToManyField(Type, db_index=True)
datetime = models.CharField(db_index=True, max_length=100, null=True)
class Type(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
这是views.py:
class all_ads(generic.ListView):
paginate_by = 12
template_name = 'new_list_view_grid-card.html'
def get_queryset(self):
city_district = self.request.GET.getlist('city_district')
usage = self.request.GET.get('usage')
status = self.request.GET.get('status')
last2week = datetime.datetime.now() - datetime.timedelta(days=14)
status = status.split(',')
if usage:
usage = usage.split(',')
else:
usage = ['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31']
intersections = list(set(status).intersection(usage))
type_q = (Q(type__in=intersections) & Q(type__isnull=False))
result = models.Catalogue.objects.filter(
Q(datetime__gte=last2week) &
type_q &
((reduce(operator.or_, (Q(city__contains=x) for x in city_district)) & Q(city__isnull=False)) |
(reduce(operator.or_, (Q(district__contains=x) for x in city_district)) & Q(district__isnull=False)))
).distinct().order_by('-datetime').prefetch_related('type')
return result
我想对带有一些查询的MySQL数据库进行过滤操作,并在列表视图中返回结果。
它在小型数据库上运行良好,但对于大型数据库,返回结果需要10秒以上的时间。如果删除type_q
查询,则需要2秒(减少10秒!)。
如何提高__in
查询集的性能?
推荐答案
看起来type_q
本身并不是真正的罪魁祸首,而是起到了乘数的作用,因为现在我们做了一个LEFT OUTER JOIN
,因此__contains
遍历了所有的组合。因此,这更是两个一起工作的筛选器的特性
我们可以使用:
省略此操作cat_ids = list(Catalogue.objects.filter(
Q(*[Q(city__contains=x) for x in city_district], _connector=Q.OR) |
Q(*[Q(district__contains=x) for x in city_district], _connector=Q.OR)
).values_list('pk', flat=True))
result = models.Catalogue.objects.filter(
Q(datetime__gte=last2week),
type_q,
pk__in=cat_ids
).distinct().order_by('-datetime').prefetch_related('type')
某些数据库(MySQL知道不是优化子查询),甚至可以用来优化子查询。因此,这里我们没有物化列表,但是让Django使用子查询:
cat_ids = Catalogue.objects.filter(
Q(*[Q(city__contains=x) for x in city_district], _connector=Q.OR) |
Q(*[Q(district__contains=x) for x in city_district], _connector=Q.OR)
).values_list('pk', flat=True)
result = models.Catalogue.objects.filter(
Q(datetime__gte=last2week),
type_q,
pk__in=cat_ids
).distinct().order_by('-datetime').prefetch_related('type')
这篇关于Django-改进M2M过滤中__in查询集的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文