为什么 Django 显式地在唯一字段上创建索引

Why does Django create an index on a unique field explicitly

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

对于以下 Django 模型:

class Book(models.Model):
    name = models.TextField(unique=True)

pg_dump (PostgreSQL 9.3) 显示以下 table 和约束:

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);

但是 PostgreSQL documentation 说:

PostgreSQL automatically creates a unique index when a unique constraint [...] is defined for a table.

[...] there's no need to manually create indexes on unique columns; doing so would just duplicate the automatically-created index.

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

CREATE UNIQUE INDEX book_name_like ON book USING btree (name text_pattern_ops);

并且在列中根本没有 UNIQUE 约束。因此,带有 text_pattern_ops 的单个 UNIQUE INDEX 将导致 DB 不为 UNIQUE 约束创建隐式索引。

问题的核心是 Django documentation:

中做出的保证

Note that when unique is True you don’t need to specify db_index, because unique implies the creation of an index.

所以根据 Django 的约定,unique=True 意味着 db_index=True,而 db_index=True 意味着 Django 必须创建 text_pattern_ops 索引以支持所有查找类型(参见 ticket 12234).

至于仅使用单个唯一索引,PostgreSQL documentation 表示不会涵盖所有查找类型:

Note that you should also create an index with the default operator class if you want queries involving ordinary <, <=, >, or >= comparisons to use an index. Such queries cannot use the xxx_pattern_ops operator classes.

您可以尝试同时添加 unique=Truedb_index=False

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

分类:在 db_index=Falseunique=True

时接受跳过索引