Запрос Django-Postgres WHERE с использованием индекса varchar_pattern_ops вместо индекса pkey - PullRequest
1 голос
/ 23 апреля 2019

У меня есть настройка Django-Postgres с этой таблицей -

class User(models.Model):
    id = models.CharField(max_length=255, primary_key=True)

Запуск миграции создает два поля на поле (это то, что Django автоматически делает, как я проверял при запуске sqlmigrate) - один индекс для pkey и один для varchar_pattern_ops -

\d+ "user";

Column|            Type          | Modifiers | Storage  | Stats target | Description 
------+--------------------------+-----------+----------+--------------+-------------
 id   |  character varying(255)  | not null  | extended |              | 

Indexes:
"user_pkey" PRIMARY KEY, btree (id)
"user_id_90845346_like" btree (id varchar_pattern_ops)

Как я понимаю, если я выполню этот запрос

select * from "user" where id='id1234';

он должен использовать user_pkey. Вместо этого он использует user_id_90845346_like.

explain analyze select * from "user" where id='id1234';

 Index Scan using "user_id_90845346_like" on "user"  (cost=0.41..8.43 rows=1 width=770) (actual time=0.033..0.0
33 rows=0 loops=1)
   Index Cond: ((id)::text = 'id1234'::text)
 Planning time: 1.335 ms
 Execution time: 0.072 ms
(4 rows)

Я также не вижу никакой возможности заставить Postgres использовать индекс, но я действительно хочу знать, почему при поиске = не используется первичный ключ. Разве поиски like text% не должны использовать индекс varchar_pattern_ops?

1 Ответ

1 голос
/ 04 июня 2019

Драйвер postgres всегда будет выбирать индекс varchar_pattern_ops, если он существует в тех случаях, когда столбец, по которому вы индексируете, является столбцом varchar или каким-либо его вариантом. Проще говоря, поскольку ваш столбец, по которому вы индексируете, содержит строки, драйвер выберет индекс, который лучше всего работает со строками, когда он доступен. Если вы вместо этого сохранили первичные ключи как целые числа, драйвер будет использовать индекс btree.

...