Django: означает ли unique_together db_index=True так же, как это делает ForeignKey?

#python #django #django-models #database-indexes

#python #django #django-модели #база данных-индексы

Вопрос:

Поле в модели foo = models.ForeignKey(Foo) автоматически добавит индекс базы данных для столбца, чтобы ускорить поиск. Это хорошо и хорошо, но в документах Django не указано, получают ли поля в model-meta unique_together одинаковую обработку. У меня есть модель, в которой для одного поля char, которое указано в unique_together , требуется индекс для быстрого поиска. Я знаю, что добавление дубликата db_index=True в определение поля ничего не повредит, но мне любопытно.

Ответ №1:

Для тех, кто приходит сюда, задаваясь вопросом, нужно ли им index_together в дополнение к unique_together , чтобы получить преимущество в производительности индекса, ответ для Postgres — нет, они функционально одинаковы.

Комментарии:

1. Отличное дополнение, Том. Спасибо за это.

2. Спасибо за дополнительную информацию! Пытался исправить неработающую ссылку, но не могу найти рабочую. Можете ли вы, пожалуйста, исправить ссылку или удалить ее вообще?

Ответ №2:

Если unique_together добавить индекс, это будет индекс с несколькими столбцами.

Если вы хотите, чтобы один из столбцов индексировался индивидуально, я полагаю, вам нужно указать db_index=True в определении поля.

Комментарии:

1. Я могу подтвердить это из postgresql, вот пример из консоли postgresql индекса uniquere_toguether: public | registration_something | registration_something_field_5c0b3bdb9d08b87c_uniq | | CREATE UNIQUE INDEX registration_something_field_5c0b3bdb9d08b87c_uniq ON registration_something USING btree (field1, field2)

Ответ №3:

unique_together автоматически не добавляет индексы для каждого поля, включенного в список.

Новые версии Django предлагают вместо этого использовать метапараметры Index amp; constraint:

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/

И пример модели из проекта с открытым исходным кодом:

класс GroupResult(модели.Модель): «»»Результат / статус группы задач.»»»

 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']),
    ]
  

Комментарии:

1. Привет, спасибо за этот новый ответ. Новый constraint API потрясающий. Я добавил немного выше вашего ответа, чтобы ответить непосредственно на исходный вопрос, так что я могу исключить это как новый правильный ответ, потому что сейчас он гораздо более актуален.

Ответ №4:

В Django 1.5 и выше вы можете использовать атрибут {Model}.Meta.index_together class . Если бы у вас было два поля с именем foo и bar , вы бы добавили:

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

Если у вас есть только один набор уникальных полей, вы можете использовать одномерную итерацию for 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'
  

Комментарии:

1. index_together с 2 полями отличается от db_index=True для тех же 2 полей. index_together позволяет объединить несколько индексов в 1, чтобы WHERE a = 5 AND b = 10 можно было сравнивать предложения типа like, пока база данных сканирует один индекс.

Ответ №5:

Согласно документам, он будет обеспечивать уникальность только на уровне базы данных. Я думаю, что обычно создание уникального поля не подразумевает, что у него есть индекс. Хотя вы также можете просто проверить на уровне БД, существует ли индекс. Все указывает, хотя это не так.

Комментарии:

1. «Подразумеваемая» часть моего вопроса относится к поведению, специфичному для Django. models.ForeignKey устанавливается db_index=True по умолчанию в определении поля. Я также считаю, что unique=True поле также создает индекс (на уровне базы данных), благодаря чему уникальные проверки выполняются быстро (поправьте меня, если я ошибаюсь).

2. Я думаю, это зависит от того, как ваш компонент database engine обрабатывает УНИКАЛЬНЫЕ ограничения. Большинство из них устанавливают индекс, если я прав. Однако это не имеет никакого отношения к Django.

3. Действительно, эта models.ForeignKey часть имеет отношение к Django, а не к unique=True . Я упомянул об unique=True этом в стороне, из-за making a field unique does not... части вашего ответа.

4. unique_together также применяется на уровне базы данных, а не в Django. Предполагая, что ваш компонент Database engine автоматически поддерживает индексы для уникальных столбцов, индекс будет установлен. Если нет, то нет. Это ваш ответ. Кроме того, просмотр кода Django не указывает, что они будут устанавливать индекс db для a unique_together .