Django-Postgres, ГДЕ запрос с использованием индекса varchar_pattern_ops вместо индекса pkey

#django #postgresql #postgresql-9.5 #database-indexes #django-1.9

#django #postgresql #postgresql-9.5 #база данных-индексы #django-1.9

Вопрос:

У меня есть настройка 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:

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