为什么Django明确地在唯一字段上创建索引

use*_*ser 8 sql django postgresql django-models postgresql-9.3

更新:通过psql进一步的实验简化Q :

对于以下Django模型:

class Book(models.Model):
    name = models.TextField(unique=True)
Run Code Online (Sandbox Code Playgroud)

pg_dump (PostgreSQL 9.3)显示了以下表格和约束:

CREATE TABLE book (
    id integer NOT NULL,
    name text NOT NULL,
);

ALTER TABLE ONLY book ADD CONSTRAINT book_name_key UNIQUE (name);

CREATE INDEX book_name_like ON book USING btree (name text_pattern_ops);
Run Code Online (Sandbox Code Playgroud)

但PostgreSQL 文档说:

当为表定义唯一约束[...]时,PostgreSQL会自动创建唯一索引.

[...] 无需在唯一列上手动创建索引; 这样做只会复制自动创建的索引.

问题:为什么Django会在一个唯一的列上创建索引呢?也许理由是它使用运算符类text_pattern_ops,因此Django需要添加另一个索引.如果是这种情况,更好的方法是将unique=TrueDjango的约束解释为:

CREATE UNIQUE INDEX book_name_like ON book USING btree (name text_pattern_ops);
Run Code Online (Sandbox Code Playgroud)

根本没有UNIQUE列中的约束.因此,单个UNIQUE INDEXwith text_pattern_ops将导致DB不为UNIQUE约束创建隐式索引.

Kev*_*nry 16

问题的核心是Django文档中的这种保证:

请注意,当uniqueTrue你并不需要指定db_index,因为unique意味着索引的创建.

因此,通过Django的契约unique=True暗示db_index=True,并且db_index=True意味着Django必须创建text_pattern_ops索引以支持所有查找类型(参见权证12234).

至于只使用一个唯一索引,PostgreSQL文档说这不会涵盖所有查找类型:

请注意,如果您希望涉及普通<,<=,>或> =比较的查询使用索引,则还应使用默认运算符类创建索引.此类查询不能使用xxx_pattern_ops运算符类.

您可以尝试添加unique=Truedb_index=False.


use*_*ser 5

错误报告中的详细讨论:https : //code.djangoproject.com/ticket/24082

分类:接受在db_index=False(with unique=True)时跳过索引