将 Django ORM 查询从多个数据库查找优化为可能的一个数据库查找
Optimizing Django ORM query from multiple DB look-ups to possibly one DB look-up
在我维护的一个基于 Django 的社交网站中,用户 post 照片。每张 posted 照片都是一个照片流的一部分(即相关照片列表)。我通过 CBV (ListView) 的 get_queryset
方法计算了 200 张最近的照片:
def get_queryset(self):
return Photo.objects.order_by('-id')[:200]
接下来,对于每张照片,我附加 count
相关照片的存在数量。我首先检查每张照片属于哪个照片流,然后从所述流中获取其他照片,最后根据新鲜度排除一些照片。换句话说:
for obj in context["object_list"]:
count = Photo.objects.filter(which_stream=obj.which_stream).order_by('-upload_time').exclude(upload_time__gt=obj.upload_time).count()
然后 count
与每个 obj
配对,这样我最终得到一个字典用于填充模板。正如您所猜到的,我基本上使用此信息来显示相关照片的数量以及每张列出的照片。
但是这样做的数据库查询太多了! 为了提高性能,我该如何优化它?请指教!
这是具有相关字段的 photo
和 photostream
数据模型:
class Photo(models.Model):
owner = models.ForeignKey(User)
which_stream = models.ForeignKey(PhotoStream)
image_file = models.ImageField(upload_to=upload_photo_to_location, storage=OverwriteStorage())
upload_time = models.DateTimeField(auto_now_add=True, db_index=True)
class PhotoStream(models.Model):
stream_cover = models.ForeignKey(Photo)
children_count = models.IntegerField(default=1)
creation_time = models.DateTimeField(auto_now_add=True)
请检查您是否可以像这样使用 Conditional Aggregations:
from django.db.models import Count, Case, When, IntegerField
Photo.objects.annotate(
count=Count(Case(
When(which_stream__photo__upload_time__lte=F('upload_time')), then=1),
output_field=IntegerField(),
))
).order_by('-id')[:200]
我还没有测试过这个,但我想你会知道如何使用它。
在我维护的一个基于 Django 的社交网站中,用户 post 照片。每张 posted 照片都是一个照片流的一部分(即相关照片列表)。我通过 CBV (ListView) 的 get_queryset
方法计算了 200 张最近的照片:
def get_queryset(self):
return Photo.objects.order_by('-id')[:200]
接下来,对于每张照片,我附加 count
相关照片的存在数量。我首先检查每张照片属于哪个照片流,然后从所述流中获取其他照片,最后根据新鲜度排除一些照片。换句话说:
for obj in context["object_list"]:
count = Photo.objects.filter(which_stream=obj.which_stream).order_by('-upload_time').exclude(upload_time__gt=obj.upload_time).count()
然后 count
与每个 obj
配对,这样我最终得到一个字典用于填充模板。正如您所猜到的,我基本上使用此信息来显示相关照片的数量以及每张列出的照片。
但是这样做的数据库查询太多了! 为了提高性能,我该如何优化它?请指教!
这是具有相关字段的 photo
和 photostream
数据模型:
class Photo(models.Model):
owner = models.ForeignKey(User)
which_stream = models.ForeignKey(PhotoStream)
image_file = models.ImageField(upload_to=upload_photo_to_location, storage=OverwriteStorage())
upload_time = models.DateTimeField(auto_now_add=True, db_index=True)
class PhotoStream(models.Model):
stream_cover = models.ForeignKey(Photo)
children_count = models.IntegerField(default=1)
creation_time = models.DateTimeField(auto_now_add=True)
请检查您是否可以像这样使用 Conditional Aggregations:
from django.db.models import Count, Case, When, IntegerField
Photo.objects.annotate(
count=Count(Case(
When(which_stream__photo__upload_time__lte=F('upload_time')), then=1),
output_field=IntegerField(),
))
).order_by('-id')[:200]
我还没有测试过这个,但我想你会知道如何使用它。