数据库操作Django过滤器速度慢

问题描述 投票:0回答:2

我必须筛选一个大约 2400 万的模型。实例(记录)。 我需要根据从 url kwarg 获得的一些名称来过滤它们,我有这样的东西:

Model.objects.filter(field__icontains=self.kwargs['kwarg']).values()
在视图上。

这绝对没有效率,因为页面速度非常慢并且需要 CPU 进行大量处理。我该如何解决这个问题?

提前感谢您的回答!

django postgresql performance django-queryset database-performance
2个回答
0
投票

在字段上创建索引。其效果如何会因数据库引擎的不同而有所不同,但应该会有所帮助。在

db_index=True
的模型定义中添加
field
。您还可以查看 PostgreSQL 全文索引


0
投票

您必须在该字段上创建索引。但它必须是一个特定的索引才能与

__icontains
过滤器相关。

完整分析在这里:https://medium.com/metakratos-studio/how-we-optimized-i-queries-and-found-inaccuracies-in-django-documentation-d921a44d8bc4

模型定义中的

db_index=True
创建了一个B树索引,可以处理相等和范围查询。这仅对 django 中的
__exact
文件管理器(SQL 中的 = 运算符)有用。即使与
__iexact
过滤器一起使用也不会使用它,因为该过滤器在 SQL 中 = 运算符之前对数据使用 SQL 操作 UPPER。这需要自定义索引或使用 Django 3.2+ OpClass 表达式。

对于

__contains
过滤器,LIKE 运算符在 SQL 中使用,并且需要 Postgres Trigram 扩展来进行全文搜索。特别是杜松子酒指数似乎效果最好。

__icontains
过滤器可以使用Gin索引,但与
__iexact
过滤器一样,它还在LIKE运算符之前对数据使用UPPER SQL操作。所以它需要一个自定义的 Gin 索引或使用 Django 3.2+ 的
OpClass
表达式。

所以对于后者,我必须在模型中使用它:

from django.contrib.postgres.indexes import GinIndex, OpClass

  class Meta:
      indexes = [
          GinIndex(fields=['name'], name='name_gin_index',
opclasses=['gin_trgm_ops'])
      ]

您还需要在创建索引之前将

TrigramExtension()
(
from django.contrib.postgres.operations import TrigramExtension
) 添加到迁移操作列表中来激活迁移中的 Trigram 扩展

© www.soinside.com 2019 - 2024. All rights reserved.