django - 上索引似乎不适用于 iexact Django 字段查找
问题描述
我有一些引用(字符串),我想用它们来过滤不区分大小写的完全匹配的查询。为此,我使用了iexact
Django 字段查找。
Model.objects.filter(column1__iexact=reference)
由于该表上有大量行,因此我想创建一个索引来加快查询速度。Django 使用 UPPER 函数来执行iexact
查找。所以我创建了以下迁移(数据库是 Postgresql):
class Migration(migrations.Migration):
dependencies = [
('app', 'previous_migr'),
]
operations = [
migrations.RunSQL(
sql=r'CREATE INDEX "index_name_idx" ON "table" (UPPER("column1") );',
reverse_sql=r'DROP INDEX "index_name_idx";'
),
]
不幸的是,查询时似乎没有使用此索引。
为什么我会这样想?以下是请求时间:
- iexact ~= 17s
- 精确 < 1s
这是生成的(截断的)SQL 查询:
SELECT "table"."id" FROM "table"
WHERE (
"table"."is_removed" = false
AND (UPPER("table"."column1"::text) = UPPER('blablabla')
OR UPPER("ordering_order"."column2"::text) = UPPER('blablabla')))
ORDER BY "table"."id" ASC
)
我的迁移有问题吗?还有其他选择可以以良好的性能执行此查询吗?
解决方案
Upper
您可以使用查询中的表达式进行过滤,因此:
from django.db.models import Upper
Model.objects.annotate(
column1_upper=Upper('column1')
).filter(column1_upper=reference.upper())
或者在django-3.2中,我们可以使用 a.alias(…)
来稍微提高性能:
Model.objects.alias(
column1_upper=Upper('column1')
).filter(column1_upper=reference.upper())
然而,以上不是不区分大小写的搜索。当您将两个项目都转换为小写/大写时,假设两个项目是等价的,这是一个常见的错误。例如,在德语中,eszett ß为大写字母'SS'
,其他字符没有小写/大写变体。为了匹配大小写不变,您需要看一下 casefolding。
推荐阅读
- php - 使用 oneToMany 关系将动态字段数据数组保存到数据库
- do-while - 当一个条件等于另一个条件但有异常时,如何执行循环?
- reactjs - 导致 React 组件受控/不受控的条件是什么?我有一个改变的例子?
- c# - ASP.NET Framework 中的自定义基于策略的授权
- angular - Angular 5 - 反应形式
- java - 如何将 Flux 分组到桶中并在桶在一段时间后未达到一定大小时发出警报
- java - 我无法访问流派类
- javascript - Javascript循环遍历多个表单,获取所有输入值
- c++ - 为什么我不能正确计算 C++ 中的大整数值?
- python - 点对多点的Python部署解决方案