我正在使用 Django 创建一些数据库表,如下所示:
class MetadataTerms(models.Model):
term = models.CharField(max_length=200)
size = models.IntegerField(default=0)
validity = models.IntegerField(default=0, choices=TERM_VALIDITY_CHOICES)
然后我运行查找查询以找到具有正确 term
的适当行,以不区分大小写的方式匹配。例如:
MetadataTerms.objects.filter(term__iexact=search_string, size=3)
此查找子句在 SQL 中转换为类似这样的内容:
SELECT "app_metadataterms"."id", "app_metadataterms"."term", "app_metadataterms"."size" FROM "app_metadataterms" WHERE (UPPER("app_metadataterms"."term"::text) = UPPER('Jack Nicklaus survives') AND "app_metadataterms"."size" = 3 );
在 Postgres 上,我可以对上面的内容执行一个 EXPLAIN
查询,我得到这个查询计划:
QUERY PLAN
-----------------------------------------------------------------------------------
Seq Scan on app_metadataterms (cost=0.00..1233.01 rows=118 width=21)
Filter: ((size = 3) AND (upper((term)::text) = 'JACK NICKLAUS SURVIVES'::text))
因为 term
字段没有索引,也没有以大小写规范化的方式索引,所以上面的查询需要对所有数据库行执行缓慢的 Seq[uential] 扫描操作。
然后我插入一个简单的大小写标准化索引,例如:
CREATE INDEX size_term_insisitive_idx ON app_metadataterms (upper(term), size);
上面的查询现在运行速度快了大约 6 倍:
QUERY PLAN
---------------------------------------------------------------------------------------------
Bitmap Heap Scan on app_metadataterms (cost=5.54..265.15 rows=125 width=21)
Recheck Cond: ((upper((term)::text) = 'JACK NICKLAUS SURVIVES'::text) AND (size = 3))
-> Bitmap Index Scan on size_term_insisitive_idx (cost=0.00..5.51 rows=125 width=0)
Index Cond: ((upper((term)::text) = 'JACK NICKLAUS SURVIVES'::text) AND (size = 3))
我的问题是:如何将高级数据库索引的创建注入(inject)到 Django 模型管理命令中?
最佳答案
Django 1.11(2.0 应该也可以)+ PostgreSQL:
首先,创建一个空迁移:
python3 manage.py makemigrations appName --empty
Django 使用
UPPER
进行不精确查找。因此,创建一个迁移以添加一个UPPER(yourField)
索引:# -*- coding: utf-8 -*- # Generated by Django 1.11.7 on 2017-12-14 23:11 from __future__ import unicode_literals from django.db import migrations class Migration(migrations.Migration): dependencies = [ ('stats', '0027_remove_siteuser_is_admin'), ] operations = [ migrations.RunSQL( sql=r'CREATE INDEX "stats_siteuser_upper_idx" ON "stats_siteuser" (UPPER("email"));', reverse_sql=r'DROP INDEX "stats_siteuser_upper_idx";' ), ]
关于database - 如何在 Django 中创建不区分大小写的数据库索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18597986/