Индекс не используется для django desc
У меня есть модель django со следующими индексами:
class Meta:
indexes = [
models.Index(fields=['-current']),
models.Index(fields=['current']),
]
Соответствующее поле определяется как:
current = models.IntegerField(null=True)
Они были добавлены, я запустил миграцию и увидел результаты:
companies/migrations/0294_auto_20220110_1155.py
- Create index companies_c_current_f2c815_idx on field(s) -current of model company
- Create index companies_c_current_c8bcb7_idx on field(s) current of model company
Я обнаружил, что выполнение запроса django-rest-framework с ording=current в ~5 раз быстрее, чем с ording=-current. Используя PSQL explain, я получаю следующее:
# explain select * from company order by current desc nulls last limit 100;
QUERY PLAN
--------------------------------------------------------------------------------------------------------
Limit (cost=41028.75..41040.42 rows=100 width=1223)
-> Gather Merge (cost=41028.75..68747.19 rows=237570 width=1223)
Workers Planned: 2
-> Sort (cost=40028.73..40325.69 rows=118785 width=1223)
Sort Key: current DESC NULLS LAST
-> Parallel Seq Scan on companies_company (cost=0.00..35488.85 rows=118785 width=1223)
(6 rows)
# explain select * from company order by current asc nulls last limit 100;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.42..49.79 rows=100 width=1223)
-> Index Scan Backward using companies_c_current_f2c815_idx on companies_company (cost=0.42..140727.06 rows=285084 width=1223)
(2 rows)
Из вышесказанного ясно, что asc использует индекс, а desc - нет, что объясняет разницу во времени. Мой вопрос: почему нет? Есть ли другой способ добавления индекса, чтобы убедиться, что он используется и для asc, и для desc? Первоначально я пытался добавить его в определение поля модели с помощью db_index=True
, но это привело к той же проблеме.
Индекс можно сканировать в обоих направлениях, но он должен быть отсортирован точно так же, как пункт ORDER BY
, для которого он предназначен по умолчанию. Обычный индекс сортируется в порядке ASC NULLS LAST
, поэтому он может поддерживать этот порядок или обратный, а именно DESC NULLS FIRST
. Чтобы создать индекс, который может поддерживать ваш пункт ORDER BY
, используйте
CREATE INDEX ON companies_company (current ASC NULLS FIRST);