#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 для aunique_together
.