【发布时间】:2021-07-03 15:02:17
【问题描述】:
我有一个模型与另一个模型具有 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 查询集的性能?
【问题讨论】:
-
如果您将
Q(type__in=intersections)用于type_q会怎样? -
@WillemVanOnsem 效果不大……需要10秒
-
可能不是
type_q是问题所在,而是type_q充当“乘数”,因此city__contains和detrict__contains现在需要枚举相同的记录多次。 -
如果您没有索引,您可能还需要在该
datetime字段上创建索引(您正在使用order_by)。 -
如果您先查询
cids = Catalogue.objects.filter((reducue__...).values('pk'),然后使用.filter(Q(datetime__gte=last2week) & type_q & pk__int=cids,该怎么办?