例如在学校,有很多数据来存储例如“Class”,“Student”,“Book”等。另外,该模型使用了softdelete(softdelete是指删除时的操作只需将
is_deleted
更改为True
在模型中)。每个模型中都有create_time
、update_time
、is_delete
等。在我的代码中现在我使用下面的方法,运行sql至少花了30s。
那么使用包含很多条件的过滤器来查询
Count
最优化的方式是什么?有时我们还需要计算相同的模型但使用不同的过滤器
这是 Django 中的代码示例(检查每所学校的计数数据)。
# In this code, each model already implements softdelete manager query.
School.objects.annotate(
number_of_class=Count(
"class", filter=Q(class__is_deleted=False, class__create_time__lte=datetime, ...more filter), distinct=True
),
number_of_student=Count(
"student", filter=Q(student__is_deleted=False, student__create_time__lte=datetime, ...more filter), distinct=True
),
number_of_public_book=Count(
"book", filter=Q(book__is_deleted=False, book__create_time__lte=datetime, book__create_time__gte=datetime, book__type=1, ...more filter), distinct=True
),
number_of_private_book=Count(
"book", filter=Q(book__is_deleted=False, book__create_time__lte=datetime, book__create_time__gte=datetime, book__type__in=[2,3], ...more filter), distinct=True
)
more_count...
)
请帮助提供您知道的所有代码查询以及您认为可以优化以使用许多计数和过滤器进行计数的所有代码查询。
由于您每次都过滤掉已删除的书籍,因此您已经可以通过以下方式从所有计数中忽略这些书籍:
School.objects.filter(
book__is_deleted=False,
book__create_time__lte=datetime,
book__create_time__gte=datetime,
).annotate(
number_of_public_book=Count('book', filter=Q(book__type=1)),
number_of_private_book=Count('book', filter=Q(book__type__in=[2, 3])),
)
此外不要在同一查询中对不同的
JOIN
进行聚合:这会“炸毁”记录,因为现在我们每所学校的每本书和每个班级都有一行,这意味着您必须与distinct=True
[Django-doc] 会减慢进程,对您加入的每个表进行查询。因此,在这种情况下,一个用于书籍,一个用于课程,等等。在此类查询中,您可以对书籍进行不同的计数,就像上面的代码示例中所做的那样。
最后在 db_index=True
和 is_deleted
上添加
create_time
[Django-doc]
以提高性能。