28

模型上的一个字段,foo = models.ForeignKey(Foo)会自动为该列添加一个数据库索引,以使查找更快。这很好,但是 Django 的文档没有说明模型元中的字段是否unique_together接受相同的处理。我碰巧有一个模型,其中列出的一个 char 字段unique_together需要一个索引以进行快速查找。我知道db_index=True在字段定义中添加重复项不会有任何伤害,但我很好奇。

4

5 回答 5

34

对于任何来到这里想知道他们是否需要除以index_together获取unique_together索引的性能优势的人来说,Postgres 的答案是否定的,它们在功能上是相同的。

于 2017-03-08T16:23:44.303 回答
13

如果unique_together确实添加了索引,它将是一个多列索引。

如果您希望单独索引其中一列,我相信您需要db_index=True在字段定义中指定。

于 2011-10-20T11:01:31.700 回答
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']),
    ]
于 2019-05-22T06:42:10.100 回答
7

Django 1.5 及更高版本中,您可以使用{Model}.Meta.index_togetherclass 属性。如果您有两个名为fooand的字段bar,您将添加:

class Meta(object):
    index_together = unique_together = [
        ['foo', 'bar']
    ]

如果您只有一组唯一字段,则可以对unique_together. 但是,文档并未表明这同样适用于index_together.

这也可以:

class Meta(object):
    unique_together = 'foo', 'bar'
    index_together = [
        ['foo', 'bar']
    ]

但是,文档支持这一点:

class Meta(object):
    unique_together = 'foo', 'bar'
    index_together = 'foo', 'bar'
于 2014-05-08T17:42:52.120 回答
1

根据文档,它只会在数据库级别强制执行唯一性。我认为通常使字段唯一并不意味着它具有索引。尽管如果索引存在,您也可以简单地检查数据库级别。一切都表明虽然它没有。

于 2011-10-20T01:45:16.107 回答