Изменения плана запроса Postgres для идентичного запроса при использовании pg_hint_plan

#postgresql #pg-hint-plan

#postgresql #pg-подсказка-план

Вопрос:

(Postgres 11.7)

Я использую Rows pg_hint_plan подсказку для динамического исправления неправильной оценки количества строк.

Мой запрос принимает массив аргументов, которые unnest редактируются и присоединяются к остальной части запроса в качестве предиката. По умолчанию планировщик запросов всегда предполагает, что этот массив-аргумент содержит 100 записей, тогда как в действительности это число может сильно отличаться. Эта неверная оценка привела к плохим планам запросов. Я устанавливаю количество строк окончательно из вызывающего приложения, изменяя текст подсказки для каждого запроса.

Иногда кажется, что этот подход работает, но я вижу какое-то странное поведение при тестировании запроса (в DBeaver).

Если я начинаю с совершенно нового соединения, когда я explain выполняю запрос (или даже просто запускаю его), подсказка, похоже, игнорируется для первых 6 выполнений, но после этого она начинает интерпретироваться правильно. Это неизменно воспроизводимо: я вижу, что оценки количества строк-нарушителей меняются при 7-м выполнении нового соединения.

Что еще более интересно, запрос также использует некоторые immutable функции () для выполнения некоторых операций поиска. Если я удалю их и заменю их эквивалентным CTE или вложенным выбором, это странное поведение, похоже, исчезнет, и подсказки все время оцениваются правильно, даже при новом подключении.

Что может быть причиной того, что он не выполняет pg_hint_plan подсказки до тех пор, пока в этом сеансе не будет выполнено 6 запросов? Почему наличие функций влияет на подсказки?

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

1. Используете ли вы драйвер JDBC и подготовленные инструкции?

2. Драйвер JDBC да. Я явно не готовлю инструкции, нет. (спасибо!)

Ответ №1:

Поскольку вы используете JDBC, попробуйте prepareThreshold установить параметр connection равным 1, как подробно описано в документации.

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

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

1. Спасибо: для so prepareThreshold было установлено значение 5. Я попытался изменить его на 1 (а также 0 — отключить подготовку), но поведение осталось прежним.

2. Тогда это может быть связано с пользовательскими планами в PostgreSQL. Если у вас PostgreSQL версии 12 или выше, попробуйте установить plan_cache_mode значение force_generic_plan .

3. В настоящее время мы только на 11.7, но я могу обновить и протестировать его… Спасибо