【问题标题】:Why does Django create an index on a unique field explicitly为什么 Django 显式地在唯一字段上创建索引
【发布时间】:2015-03-03 07:06:23
【问题描述】:

更新:进一步简化关于psql 试验的 Q:

对于以下 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 INDEXtext_pattern_ops 将导致 DB 不会为 UNIQUE 约束创建隐式索引。

【问题讨论】:

  • 那个pg_dump SQL和Django's sqlall command的输出一样吗?
  • @KevinChristopherHenry 对于 Django 1.7,我正在使用 sqlmigrate,它应该与 sqlall 对迁移的应用程序执行相同的操作。是的,sql 是相似的。它在 create table 语句和另一个 create index 语句中有唯一约束。

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


【解决方案1】:

问题的核心是Django documentation

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

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

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

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

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

【讨论】:

  • 我已经尝试过 db_index=Falseunique=True。它没有帮助。我觉得 Django 为唯一字段创建索引的前提是不正确的(至少对于 PostgreSQL 和其他一些数据库)。此错误报告code.djangoproject.com/ticket/24082 中的更多详细信息。关于 bug 12234,创建唯一索引将是替代唯一约束和索引的更好解决方案。
  • @buffer:我在错误报告中发表了我的想法,但简要地说:我同意如果 Django 不这样做会更好,但由于这是记录在案的行为,你可能会坚持下去有一段时间(我同意明确的db_index=False 不会阻止索引的创建是一个错误)。至于您创建单个唯一索引的建议,我在上面引用的 PostgreSQL 文档清楚地表明这是行不通的。
  • 同意第一个建议,怀疑第二个。我将在错误报告中继续讨论。
【解决方案2】:

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

分类:当db_index=False(带有unique=True)时接受跳过索引

【讨论】:

    猜你喜欢
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2021-11-11
    • 1970-01-01
    相关资源
    最近更新 更多