Django+Postgres设置字符串主键时删除重复数据库索引的方法
问题原因
你看到的3个索引里,只有xxx_pk后缀的是Postgres为主键约束自动生成的必要B树索引,剩下两个都是冗余索引,生成原因通常为两类:
xxx_uniq后缀索引:要么是模型本身、继承的Common基类里给主键字段额外加了unique=True/db_index=True参数,要么是公共基类、第三方Django包没有做主键字段判断,自动给字段加了重复的唯一索引/普通B树索引。主键本身自带非空、唯一约束,对应的主键B树索引已经可以覆盖等值查询、唯一校验的所有需求,额外的唯一索引完全多余。xxx_like后缀索引:这个是带varchar_pattern_ops操作符类的B树索引,原本用来优化前缀匹配的LIKE 'xxx%'查询。如果你的数据库用的是C/POSIX排序规则,或者Postgres版本在12及以上,默认的主键B树索引已经可以支持这类前缀模糊查询,不需要额外建索引。这类索引一般是Postgres相关扩展包、项目自定义的自动加索引逻辑生成的,没有判断字段为主键就重复创建。
这类冗余索引确实会额外占用存储,还会在数据插入、更新、删除时带来三倍的索引维护开销,数据量上去后性能损耗会非常明显。
解决方法
- 先定位索引生成源头
- 检查
Common公共基类,看有没有自定义的字段自动加索引逻辑、Meta全局索引配置,有没有给所有CharField默认加普通索引、加LIKE优化索引的逻辑,补充主键判断逻辑,跳过主键字段即可。 - 检查项目安装的Django Postgres相关扩展包,找到自动建索引的配置项,把主键字段加入排除列表。
- 检查
- 清理已有的冗余索引
生成迁移文件删除已经创建的两个冗余索引即可,示例迁移代码:
注意:删索引前可以查询Postgres的from django.db import migrations class Migration(migrations.Migration): dependencies = [ # 替换为SavedCard模型所在app的最新迁移依赖 ('your_app', '00xx_last_migration'), ] operations = [ migrations.RemoveIndex( model_name='savedcard', name='prefix_savedcard_token_6c141ea4_like', ), migrations.RemoveIndex( model_name='savedcard', name='prefix_savedcard_token_6c141ea4_uniq', ), ]pg_stat_user_indexes系统视图,确认这两个索引的扫描次数为0、确实没有被业务查询使用,避免影响正常业务。 - 避免后续重复生成
- 主键字段不要额外加
db_index=True、unique=True参数,Django会自动为主键创建对应的约束和索引,重复声明会触发冗余索引生成。 - 如果是第三方包自动生成的索引,又没法通过配置跳过,可以在每次生成迁移文件后,检查迁移里的
AddIndex操作,手动删掉创建这两个冗余索引的代码再执行迁移。
- 主键字段不要额外加
内容的提问来源于stack exchange,提问作者Yash Kumar Verma
相关产品推荐
相关产品推荐

