Django: unique_together是否像ForeignKey那样隐含db_index=True?

33 投票
5 回答
11781 浏览
提问于 2025-04-17 04:40

在一个模型中,如果你定义了一个字段,比如 foo = models.ForeignKey(Foo),Django会自动为这个字段在数据库中创建一个索引,这样查找数据会更快。这是个好事,但Django的文档没有说明在模型的 unique_together 中列出的字段是否也会自动得到这样的处理。我有一个模型,其中一个字符字段被列在 unique_together 中,我希望它能有一个索引,以便快速查找。我知道在字段定义中加上重复的 db_index=True 不会有什么坏处,但我还是很好奇这个问题。

5 个回答

14

如果 unique_together 添加了一个索引,那这个索引会是多个列的组合索引。

如果你想让其中某一列单独有一个索引,我认为你需要在字段定义中指定 db_index=True

39

如果你在这里想知道,是否需要在使用 unique_together 的同时再加上 index_together 来提高索引的性能,答案是对于Postgres来说,不需要,这两者在功能上是一样的。

8

unique_together 并不会自动为列表中的每个字段添加索引。

新的 Django 版本建议使用索引和约束的元选项来代替:

https://docs.djangoproject.com/en/3.2/ref/models/options/#unique-together

https://docs.djangoproject.com/en/3.2/ref/models/options/#index-together

https://docs.djangoproject.com/en/dev/ref/models/indexes/

还有一个来自开源项目的示例模型:

class GroupResult(models.Model):
"""任务组的结果/状态。"""

group_id = models.CharField(
    max_length=getattr(
        settings,
        "DJANGO_CELERY_RESULTS_TASK_ID_MAX_LENGTH",
        255
    ),
    unique=True,
    verbose_name=_("Group ID"),
    help_text=_("Celery ID for the Group that was run"),
)
date_created = models.DateTimeField(
    auto_now_add=True,
    verbose_name=_("Created DateTime"),
    help_text=_("Datetime field when the group result was created in UTC"),
)
date_done = models.DateTimeField(
    auto_now=True,
    verbose_name=_("Completed DateTime"),
    help_text=_("Datetime field when the group was completed in UTC"),
)
content_type = models.CharField(
    max_length=128,
    verbose_name=_("Result Content Type"),
    help_text=_("Content type of the result data"),
)
content_encoding = models.CharField(
    max_length=64,
    verbose_name=_("Result Encoding"),
    help_text=_("The encoding used to save the task result data"),
)
result = models.TextField(
    null=True, default=None, editable=False,
    verbose_name=_('Result Data'),
    help_text=_('The data returned by the task.  '
                'Use content_encoding and content_type fields to read.'))

def as_dict(self):
    return {
        'group_id': self.group_id,
        'result': self.result,
        'date_done': self.date_done,
    }

def __str__(self):
    return f'<Group: {self.group_id}>'

objects = managers.GroupResultManager()

class Meta:
    """Table information."""

    ordering = ['-date_done']

    verbose_name = _('group result')
    verbose_name_plural = _('group results')

    indexes = [
        models.Index(fields=['date_created']),
        models.Index(fields=['date_done']),
    ]

撰写回答