Почему оптимизатор PostgreSQL 11 отказывается от лучшего плана, в котором будет использоваться индекс с включенным столбцом? - PullRequest
2 голосов
/ 08 октября 2019

PostgreSQL 11 недостаточно умен, чтобы использовать индексы с включенными столбцами?

CREATE INDEX organization_locations__org_id_is_headquarters__inc_location_id_ix
ON organization_locations(org_id, is_headquarters) INCLUDE (location_id);

ANALYZE organization_locations;
ANALYZE organizations;

EXPLAIN VERBOSE
SELECT location_id
FROM organization_locations ol
WHERE org_id = (SELECT id FROM organizations WHERE code = 'akron')
AND is_headquarters = 1;
QUERY PLAN
Seq Scan on organization_locations ol  (cost=8.44..14.61 rows=1 width=4)
  Output: ol.location_id
  Filter: ((ol.org_id = $0) AND (ol.is_headquarters = 1))
  InitPlan 1 (returns $0)
    ->  Index Scan using organizations__code_ux on organizations  (cost=0.42..8.44 rows=1 width=4)
          Output: organizations.id
          Index Cond: ((organizations.code)::text = 'akron'::text)

В настоящее время в Organization_locations всего 211 строк, средняя длина строки 91 байт.

Я получаю только загрузку одной страницы данных. Но ввод-вывод тот же, что и для захвата страницы индекса, и целевые данные тут же (без дополнительного просмотра страницы данных из индекса). Что PG думает с этим планом?

Это просто создает TODO для меня, чтобы округлить назад и проверить, чтобы убедиться, что правильный план начинает генерироваться, когда таблица начинает расти.

РЕДАКТИРОВАТЬ: ВотОбъяснение с буферами:

Seq Scan on organization_locations ol  (cost=8.44..14.33 rows=1 width=4) (actual time=0.018..0.032 rows=1 loops=1)
  Filter: ((org_id = $0) AND (is_headquarters = 1))
  Rows Removed by Filter: 210
  Buffers: shared hit=7
  InitPlan 1 (returns $0)
    ->  Index Scan using organizations__code_ux on organizations  (cost=0.42..8.44 rows=1 width=4) (actual time=0.008..0.009 rows=1 loops=1)
          Index Cond: ((code)::text = 'akron'::text)
          Buffers: shared hit=4
Planning Time: 0.402 ms
Execution Time: 0.048 ms

Ответы [ 2 ]

4 голосов
/ 08 октября 2019

Чтение одной страницы индекса не дешевле, чем чтение страницы таблицы, поэтому с крошечными таблицами вы не можете ожидать выигрыша от сканирования только по индексу.

Кроме того, вы

VACUUM organization_locations;

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

0 голосов
/ 08 октября 2019

В дополнение к другим ответам, это, вероятно, глупый индекс, чтобы иметь в первую очередь. ВКЛЮЧЕНО хорошо, когда вам нужен уникальный индекс, но вы также хотите прикрепить столбец, который не является частью ограничения уникальности, или когда включенный столбец не имеет операторов btree и поэтому не может быть в основной частииндекс. В других случаях вы должны просто поместить дополнительный столбец в сам индекс.

Это просто создает TODO для меня, чтобы я мог округлить назад и убедиться, что правильный план начинает генерироваться после того, как таблица зарождается.

Это проблема вашего рабочего процесса, которую вы не можете ожидать от PostgreSQL. Вы действительно думаете, что PostgreSQL должен создавать реальные планы на основе воображаемых сценариев?

...