10 Занятие 10: Производительность / Перепланирование запросов
Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета. HTML source: pgpro_10_replan.html Archive: PGPRO-handouts-16.zip Страниц PDF: 14
Page 1: Производительность / Перепланирование запросов
Авторские права
© Postgres Professional, 2023–2026 Авторы: Алексей Береснев, Илья Баштанов, Павел Толмачев, Игорь Гнатюк Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
Использование материалов курса
Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.
Page 2: Темы
- Проблема и решение
- Механизм работы
- Условия перепланирования
- Особенности реализации
Page 3: Проблема и решение
Ошибки в оценке кардинальности
- статистика устаревает из-за частых изменений данных
- неравномерное распределение данных
- параметризованные запросы и подготовленные операторы
- При сильном несоответствии
- выполнение прерывается
- запрос планируется повторно с учетом полученных данных
- Классы запросов
- тяжелые аналитические OLAP-запросы
- проблемные OLTP-запросы
Комментарии преподавателя
Как правило, ошибки при планировании вызваны некорректной оценкой кардинальности. Частая причина этого — неактуальная статистика планировщика. Например, в OLTP-системах это может быть вызвано устареванием статистики из-за часто изменяющихся данных, неравномерным распределением или использованием подготовленных запросов с параметрами (когда оптимизатор переключается на общий план выполнения).
Если в процессе выполнения запроса обнаруживается, что показатели значительно отличаются от ожидаемых, можно прервать выполнение и произвести планирование повторно, воспользовавшись накопленными в процессе выполнения дополнительными данными. Для этого необходимо настроить желаемые условия перепланирования.
Перепланирование запросов в реальном времени особенно актуально для тяжелых аналитических OLAP-запросов, для которых накладные расходы на перепланирование будут относительно невелики. Перепланирование можно использовать и для проблемных OLTP-запросов.
Page 4: Перепланирование запросов
Рассмотрим запрос:
Точное количество строк отличается от оценки. Посмотрим на параметры перепланирования:
Параметры, значения которых равны минус единице, — это условия перепланирования, которые нужно будет настроить.
Page 5: Механизм работы
{#source-figure-005 caption=“Source slide page 5: Механизм работы”}
Комментарии преподавателя
Перепланирование запросов встраивается в стандартную схему работы планировщика Postgres Pro.
Если во время или после выполнения узла плана выполняется условие перепланирования, запрос прерывается и актуальная кардинальность узлов плана (а также дополнительная служебная информация) сохраняются. Далее запускается процесс перепланирования, который может использовать сохраненную кардинальность для получения лучшего плана.
Кардинальность сохраняется только для тех узлов плана, в которых реальная кардинальность оказалась больше плановой. Эта информация хранится только в процессе перепланирования текущего запроса. Если запрос выполняется часто, новый план можно запомнить с помощью расширения pgpro_multiplan (рассматривается в теме «Сохранение планов запросов»).
Перед попыткой планирования создается вложенная транзакция. При срабатывании условия перепланирования эта транзакция обрывается и начинается новая.
Все выбранные планы для всех попыток перепланирования сохраняются в журнале сообщений сервера.
В любом случае, перепланирование необходимо использовать аккуратно и проверять его влияние на систему в целом.
Подробности можно прочитать в статье Алены Рыбакиной и Андрея Лепихова: https://habr.com/ru/companies/postgrespro/articles/819911/
Page 6: Условия перепланирования
Автоматически
- время выполнения превысило replan_query_execution_time
- узел отработал и ошибка прогноза кардинальности оказалась больше
- replan_overrun_limit
- рабочий процесс использует более replan_memory_limit памяти
- и ошибка прогноза кардинальности превысила replan_overrun_limit
- Вручную
- функция replan_signal
Комментарии преподавателя
По умолчанию перепланирование запросов отключено. Для включения достаточно установить конфигурационный параметр replan_enable и настроить условия перепланирования, или триггеры (не имеющие отношения к обычным триггерам базы данных).
В Postgres Pro Enterprise 16 перепланирование срабатывает в трех следующих случаях:
● По времени выполнения.
Запрос выполняется дольше, чем указано в параметре replan_query_execution_time.
● По ошибке оценки кардинальности после выполнения узла.
После выполнения узла плана количество обработанных строк превысило число, ожидаемое планировщиком, умноженное на значение replan_overrun_limit.
● По перерасходу памяти и ошибке оценки кардинальности во время выполнения узла.
Во время выполнения узла плана потребление памяти рабочим процессом превысило значение replan_memory_limit, а количество уже обработанных строк превысило число, ожидаемое планировщиком, умноженное на значение replan_overrun_limit.
Перепланирование можно инициировать и вручную с помощью функции replan_signal.
https://postgrespro.ru/docs/enterprise/16/realtime-query-replanning-how#RE ALTIME-QUERY-REPLANNING-TRIGGERS
Page 7: Пример перепланирования запросов
Повторим запрос:
Планировщик считает, что во внешнем наборе всего одна строка, и выбирает план без материализации. Однако в процессе выполнения запроса обнаруживается, что строк три, и в этом случае план с материализацией выглядит привлекательнее. Включим перепланирование:
Триггер по количеству строк срабатывает, если число обработанных строк превосходит ожидаемое в replan_overrun_limit раз. Пусть перепланирование срабатывает, если планировщик ошибся как минимум вдвое:
При перепланировании использовалась реальная кардинальность узлов, полученная при выполнении плана. Это привело к выбору плана с материализацией, который в данном случае более эффективен. Повторим запрос, включив вывод информации о перепланировании и добавив к команде EXPLAIN параметр verbose:
Page 8: Page 8
Теперь для узлов плана отображается более подробная информация. В нижней части вывода видно, что потребовалась одна попытка перепланирования (Replanning Attempts: 1).
Page 9: Особенности
Является частью ядра СУБД
- не нужно устанавливать расширения
- Ограничения
- поддерживает только SELECT
- не поддерживает курсоры и изменчивые функции
Комментарии преподавателя
Механизм перепланирования запросов в реальном времени является частью Postgres Pro, поэтому установки дополнительных расширений не требуется.
На данный момент у функциональности перепланирования имеются некоторые ограничения: поддерживаются только операторы SELECT (за исключением SELECT FOR UPDATE и SELECT FOR SHARE) и не поддерживаются курсоры и изменчивые (volatile) функции.
https://postgrespro.ru/docs/enterprise/16/realtime-query-replanning
В 17-й версии Postgres Pro Enterprise функциональность перепланирования переименована в адаптивное выполнение запросов (AQE, Adaptive Query Execution).
Page 10: Итоги
Если запрос выполняется неэффективно, сервер может прервать его и повторить планирование
- При перепланировании используется накопленная информация о кардинальности узлов плана
- Перепланирование позволяет автоматически ускорить проблемные запросы
Page 11: Практика
- Создайте таблицу с одним столбцом типа char(2000), с отключенной автоочисткой. Заполните ее данными.
- Получите план выполнения запроса, выполняющего декартово произведение таблицы самой с собой. Убедитесь в наличии ошибки оценки кардинальности.
- Включите перепланирование, ограничив количество попыток одной. Получите новый план.
- Снимите ограничение, установленное на количество попыток перепланирования. Сравните три получившихся плана.
Комментарии преподавателя
- Воспользуйтесь параметром конфигурации replan_max_attempts.
https://postgrespro.ru/docs/enterprise/16/runtime-config-query#GUC-REPLA N-MAX-ATTEMPTS
Page 12: 1. Таблица
Создадим базу данных и таблицу:
Вставим некоторое количество строк:
2. Стандартный планировщик
Перепланирование отключено.
Получим план выполнения запроса, соединяющего таблицу саму с собой:
Налицо ошибка оценки кардинальности в обоих узлах Seq Scan. Она связана с отключенной автоочисткой: анализ не выполнялся, планировщик не знает количество строк в таблице. Планировщик считает, что 250 строк поместятся в оперативной памяти (work_mem), поэтому вставляет узел Materialize, чтобы не считывать таблицу t2 тысячу раз с диска (или из буферного кеша). Обратите внимание, что декартово произведение всегда выполняется только вложенным циклом (подробности можно узнать из курса «QPT. Оптимизация запросов»), поэтому план в любом случае не изменится — пример носит иллюстративный, а не практический характер.
3. Перепланирование с одной попыткой
Включим перепланирование:
Page 13: Page 13
Получим новый план:
Что произошло? После завершения внутреннего цикла по таблице t2 (и одной итерации внешнего) планировщику стало известно, что в таблице t2 находится 1000 строк. Сработал триггер перепланирования. Теперь внутренний цикл выполняется по таблице t1 с промежуточным узлом материализации, поскольку планировщик все еще считает, что в t1 всего 250 строк. Кардинальность узла Seq Scan по t2 оценена верно.
4. Перепланирование с двумя попытками
Снимем ограничение на количество попыток перепланирования:
Снова получаем план:
Поскольку информация перепланирования не сохраняется между запросами, процесс повторяется. После завершения внутреннего цикла по таблице t2 планировщику стало известно, что в таблице t2 находится 1000 строк. Сработал триггер перепланирования, план был перестроен так, как мы видели в п. 3, а запрос начал выполняться с начала. Теперь после завершения внутреннего цикла по таблице t1 планировщику стало известно, что и в таблице t1 находится 1000 строк. Снова сработал триггер перепланирования, план был перестроен во второй раз. Теперь кардинальность обоих узлов Seq Scan оценена правильно; узел материализации пропал, поскольку тысяча строк не помещается в память work_mem.
Уборка
Удалим созданную базу данных.