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

时间:2015-01-05 17:29:05

标签: sql django postgresql django-models postgresql-9.3

更新:进一步尝试使用psql简化问题:

对于以下Django模型:

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

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

但是PostgreSQL documentation说:

  

PostgreSQL 在唯一时自动创建唯一索引   约束[...]是为表定义的。

     

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

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

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

并且根本没有UNIQUE约束。因此,带UNIQUE INDEX的单个text_pattern_ops会导致数据库无法为UNIQUE约束创建隐式索引。

2 个答案:

答案 0 :(得分:15)

问题的核心是Django documentation中的保证:

  

请注意,当uniqueTrue时,您无需指定db_index,因为unique意味着创建索引。

因此,根据Django的合同,unique=True暗示db_index=True,而db_index=True意味着Django必须创建text_pattern_ops索引以支持所有查找类型(请参阅{{3} })。

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

  

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

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

答案 1 :(得分:4)

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

分类:在db_index=Falseunique=True

时接受跳过索引