Какой вид индекса используется по умолчанию в Django
Что проверяют
Понимаете ли вы, что Django сам тип индекса не выбирает, а только генерирует CREATE INDEX, и тип задаёт база. Второй слой вопроса: какие индексы Django создаёт без вашей просьбы. Следом обычно спрашивают, как сделать частичный индекс или индекс по выражению.
Как отвечать
models.Index(fields=[...]) и db_index=True дают обычный CREATE INDEX без указания метода, поэтому получается тип по умолчанию для СУБД: B-tree в PostgreSQL и SQLite, B+-дерево в InnoDB у MySQL. Он работает на равенстве, диапазонах и сортировке.
Что Django индексирует сам:
- первичный ключ: индекс создаёт база вместе с
PRIMARY KEY; ForeignKey:db_index=Trueпо умолчанию, отключается явно, если колонка уже покрыта составным индексом;unique=TrueиUniqueConstraint: уникальное ограничение, под которым лежит уникальный индекс;SlugField: тожеdb_index=Trueпо умолчанию;- PostgreSQL: для
CharFieldиTextFieldсdb_index=Trueилиunique=TrueDjango добавляет второй индекс сvarchar_pattern_opsилиtext_pattern_ops(суффикс_like), чтобыstartswithработал по индексу.
Другие типы в PostgreSQL задаются классами из django.contrib.postgres.indexes: GinIndex для JSONField, массивов и полнотекстового поиска, GistIndex, BrinIndex для больших таблиц с естественным порядком, HashIndex. Частичный индекс делается через Index(fields=[...], condition=Q(...), name=...), индекс по выражению через Index(Lower("email"), name=...). Составные индексы описываются в Meta.indexes, старый index_together удалён.
Где спотыкаются
Отвечают «Django использует B-tree», будто это решение ORM. Точнее сказать, что Django метод не указывает и дальше работает умолчание базы.
Дублируют индексы: вешают db_index=True на ForeignKey, где он уже есть, или создают отдельный индекс на первую колонку составного.
Забывают, что обычная миграция с AddIndex на большой таблице в PostgreSQL блокирует запись. Для этого есть AddIndexConcurrently из django.contrib.postgres.operations, а миграция объявляется с atomic = False.