为什么 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=True
和 db_index=False
。
错误报告中的详细讨论:https://code.djangoproject.com/ticket/24082
分类:在 db_index=False
(unique=True
)
时接受跳过索引
更新:进一步简化 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
isTrue
you don’t need to specifydb_index
, becauseunique
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=True
和 db_index=False
。
错误报告中的详细讨论:https://code.djangoproject.com/ticket/24082
分类:在 db_index=False
(unique=True
)