#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, но я могу обновить и протестировать его… Спасибо