Postgres предпочитает неправильный индекс в простом запросе

#postgresql #indexing

Вопрос:

my_table включает в себя:

 user_id                | character varying           |           | not null |
epic_id                | text                        |           | not null |

"IDX_user" UNIQUE, btree ("user_id") WHERE status < 101
"IDX_epic" UNIQUE, btree ("epic_id") WHERE status < 101 
 

Проблемный запрос

 EXPLAIN ANALYZE SELECT * FROM my_table WHERE "epic_id" = 'asdf' and "status" < 101 LIMIT 1;

 Limit  (cost=0.28..8.29 rows=1 width=276) (actual time=0.230..0.231 rows=0 loops=1)
   ->  Index Scan using "IDX_user" on my_table  (cost=0.28..8.29 rows=1 width=276) (actual time=0.229..0.230 rows=0 loops=1)
         Filter: ("epic_id" = 'asdf'::text)
         Rows Removed by Filter: 273
 Planning Time: 0.122 ms
 Execution Time: 0.248 ms
 

Есть совершенно хороший IDX_epic . Почему мы используем IDX_user , проходя 100 строк и потенциально вызывая раздражающие блокировки, когда это используется в транзакции?

Забавные Лакомые Кусочки

  • SET random_page_cost=1 не помогает, как рекомендовали другие сообщения stackoverflow
  • На локальном он использует правильный индекс! В локальной сети всего 90 строк с status < 101
  • При выполнении внутреннего объединения "epic_id" = table.random_column план действительно используется IDX_epic .
  • "user_id" и "epic_id" разные типы, но из того, что я прочитал, разница между text и character varying близка к 0.
  • Согласно pg_stat_all_indexes , IDX_epic имеет idx_scan 9 баллов, что подтверждает, что он не используется, кроме как для моих тестов.

Комментарии:

1. Ты побежал VACUUM ANALYZE первым?

2. Вы провели недавний анализ (или вакуумный анализ) производственных таблиц?

3. Это закончилось тем, что я все исправил, спасибо >.>

Ответ №1:

Почему epicId находится в кавычках, а статус-нет? Также вы должны использовать LIKE как в epicId LIKE 'asdf' для сравнения значений столбцов со строками.

Комментарии:

1. Postgres не чувствителен к регистру, поэтому он преобразуется epicId без кавычек в epicid столбец и не может найти его. LIKE по — прежнему использует неправильный индекс.

2. мне кажется, что тогда проще, чтобы ваше имя столбца соответствовало соглашению об именовании змеиного случая и повторяло попытку

3. Ладно, теперь это дело змеи.

Ответ №2:

VACUUM ANALYZE решил проблему- ANALYZE один, скорее всего, решил бы ее.