77.1. Как это работает #
Если во время выполнения запроса срабатывает триггер перепланирования, частично выполненный запрос приостанавливается, и перепланирование в реальном времени пытается его переоптимизировать. Информация об операторе запроса, мощностях узлов непараметризованных узлов и параметризованных узлах с фактическими мощностями, превышающими прогнозы, используется для выбора нового плана и сохраняется для дальнейших переоптимизаций. Затем запрос запускается заново с использованием нового плана. Триггеры перепланирования могут быть отключены для будущих переоптимизаций того же запроса в следующих ситуациях:
Во время выполнения не было получено новых данных. В этом случае вывод команды
EXPLAIN ANALYZEсодержит сообщение:Replan Deactivation Reason: no new learning data(причина отключения перепланирования: отсутствуют новые данные для обучения).Сформированный повторно план совпадает с ранее использованным. В этом случае вывод команды
EXPLAIN ANALYZEсодержит сообщение:Replan Deactivation Reason: repeated plan(причина отключения перепланирования: повторный план).Достигнуто максимальное количество перезапусков, заданное параметром конфигурации replan_max_attempts. В этом случае вывод команды
EXPLAIN ANALYZEсодержит сообщение:Replan Deactivation Reason: attempt limit reached(причина отключения перепланирования: достигнут лимит попыток).Расширение, например pgpro_multiplan, отключило триггеры перепланирования. В этом случае вывод команды
EXPLAIN ANALYZEсодержит сообщение:Replan Deactivation Reason: external deactivation(причина отключения перепланирования: внешняя деактивация).
В таких случаях выполнение запроса продолжается без прерывания.
Если триггер перепланирования активирован, запрос, соответствующий условию триггера, выполняется в неявно созданной подтранзакции. В случае перепланирования это помогает выполнять очистку после предыдущего запроса и освобождать системные ресурсы, такие как память или дисковое пространство.
77.1.1. Триггеры перепланирования #
Следующие триггеры могут прервать запрос и запустить перепланирование:
Время выполнения запроса: триггер срабатывает, если запрос выполняется дольше, чем указано в параметре конфигурации replan_query_execution_time.
Количество обработанных кортежей узлов: триггер срабатывает, когда количество таких кортежей превышает число, обычно ожидаемое планировщиком, которое умножается на значение параметра конфигурации replan_overrun_limit.
Потребление памяти рабочим процессом: триггер срабатывает, когда потребление памяти рабочим процессом превышает значение параметра конфигурации replan_memory_limit и срабатывает триггер количества обработанных кортежей узлов.
Ручной триггер: срабатывает, когда пользователь вызывает функцию
replan_signalиз другого сеанса. В отличие от остальных триггеров, этот триггер не может быть отключён.
77.1.2. Просмотр подробностей о перепланировании #
Если параметр replan_show_signature включён, информация, связанная с перепланированием, добавляется в вывод команды EXPLAIN ANALYZE. Раздел SUMMARY дополнительно включает следующие характеристики:
Replan Active— был ли механизм перепланирования активен к моменту завершения выполнения запроса.Table Entries— количество таблиц в запросе, включая подзапросы.Controlled Statements— количество операторов, которые были перепланированы во время выполнения запроса.Replanning Attempts— общее количество перезапусков/попыток перепланирования запроса.Total Time Elapsed— общее время выполнения запроса, включая время всех попыток перезапуска/перепланирования. Это свойство отображается только в том случае, если запрос был переоптимизирован и перезапущен хотя бы один раз.Final Run Planning Time— время планирования последней переоптимизации при перепланировании. Это свойство отображается только в том случае, если запрос был переоптимизирован и перезапущен хотя бы один раз.Replan Deactivation Reason— причина отключения перепланирования. Возможные значения не требуют дополнительных пояснений:attempt limit reached(достигнут лимит попыток),repeated plan(повторный план),no new learning data(отсутствуют новые данные для обучения) илиexternal deactivation(внешняя деактивация). Отображается только в том случае, если перепланирование не было активно к моменту завершения выполнения запроса.
Для каждого узла плана включены следующие характеристики:
NodeSign— 64-битная подпись (хеш) узла, которая однозначно идентифицирует узел плана запроса. Подписаны не все узлы, а только те, где ошибки модели оценки оптимизатора могут приводить к ошибкам в поиске оптимального плана запроса.Cardinality— количество кортежей узла плана, достигнутое при предыдущих выполнениях запроса. Доступно только с параметромVERBOSE.Groups Number— количество групп, вычисленное для этого узла плана в результате предыдущих выполнений запроса. Доступно только с параметромVERBOSE.
77.1.3. Интеграция с pgpro_multiplan #
Перепланирование запросов в реальном времени может работать совместно с расширением pgpro_multiplan, предоставляя следующие возможности:
Автоматическое добавление планов, созданных с помощью перепланирования запросов в реальном времени, в список разрешённых планов, используемый расширением pgpro_multiplan.
Возможность переопределять и настраивать значения триггеров для отдельных запросов.
Сбор статистики перепланирования запросов в реальном времени для всех операторов, которые рассматриваются для переоптимизации.
Используйте параметр конфигурации pgpro_multiplan.aqe_mode для включения функциональности, связанной с перепланированием запросов в реальном времени.
77.1.4. Пример #
Пример 77.1. Использование перепланирования
В следующем примере показано использование перепланирования:
DROP TABLE IF EXISTS replan_test; CREATE TABLE replan_test WITH (autovacuum_enabled=off) AS SELECT x as x, x as y, x as z from generate_series(1, 100000) as x; INSERT INTO replan_test SELECT 1, x, x FROM generate_series(1, 1000000) as x; CREATE INDEX ON replan_test(x); CREATE INDEX ON replan_test(y); ANALYZE; set replan_show_signature = true; -- Перепланирование отключено SET replan_enable = false; EXPLAIN ANALYZE SELECT FROM replan_test t1, replan_test t2, replan_test t3 WHERE t1.x = t2.x and t1.y = t3.y and t1.y < 100 and t1.z < 100 and t2.y < 100 and t2.z < 100 and t3.y < 100 and t3.z < 100; -- Перепланирование включено триггером количества обработанных кортежей SET replan_enable = true; SET replan_overrun_limit = 2; EXPLAIN ANALYZE SELECT FROM replan_test t1, replan_test t2, replan_test t3 WHERE t1.x = t2.x and t1.y = t3.y and t1.y < 100 and t1.z < 100 and t2.y < 100 and t2.z < 100 and t3.y < 100 and t3.z < 100;
Вывод без перепланирования:
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=14.30..45.18 rows=1 width=0) (actual time=73.677..6848.136 rows=20196 loops=1)
-> Nested Loop (cost=13.87..36.72 rows=1 width=4) (actual time=73.654..6792.731 rows=10098 loops=1)
-> Index Scan using replan_test_y_idx on replan_test t1 (cost=0.43..19.25 rows=1 width=8) (actual time=0.014..0.271 rows=198 loops=1)
Index Cond: (y < 100)
Filter: (z < 100)
-> Bitmap Heap Scan on replan_test t2 (cost=13.44..17.46 rows=1 width=4) (actual time=34.278..34.295 rows=51 loops=198)
Recheck Cond: ((y < 100) AND (t1.x = x))
Filter: (z < 100)
Heap Blocks: exact=298
-> BitmapAnd (cost=13.44..13.44 rows=1 width=0) (actual time=34.268..34.268 rows=0 loops=198)
-> Bitmap Index Scan on replan_test_y_idx (cost=0.00..6.08 rows=221 width=0) (actual time=0.016..0.016 rows=198 loops=198)
Index Cond: (y < 100)
-> Bitmap Index Scan on replan_test_x_idx (cost=0.00..7.11 rows=357 width=0) (actual time=34.248..34.248 rows=505052 loops=198)
Index Cond: (x = t1.x)
-> Index Scan using replan_test_y_idx on replan_test t3 (cost=0.43..8.45 rows=1 width=4) (actual time=0.004..0.005 rows=2 loops=10098)
Index Cond: ((y = t1.y) AND (y < 100))
Filter: (z < 100)
Planning Time: 0.722 ms
Execution Time: 6849.539 ms
(19 rows)Вывод с перепланированием:
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Merge Join (cost=1.28..720.49 rows=20196 width=0) (actual time=0.038..30.495 rows=20196 loops=1)
NodeSign: 16399548477598347697
Merge Cond: (t1.y = t3.y)
-> Nested Loop (cost=0.85..624.08 rows=9998 width=4) (actual time=0.027..8.577 rows=10098 loops=1)
NodeSign: 6806589677965256871
Join Filter: (t1.x = t2.x)
Rows Removed by Join Filter: 29106
-> Index Scan using replan_test_y_idx on replan_test t1 (cost=0.43..19.25 rows=197 width=8) (actual time=0.014..0.180 rows=198 loops=1)
NodeSign: 17234727896600901988
Index Cond: (y < 100)
Filter: (z < 100)
-> Materialize (cost=0.43..20.24 rows=198 width=4) (actual time=0.000..0.013 rows=198 loops=198)
NodeSign: subordinate
-> Index Scan using replan_test_y_idx on replan_test t2 (cost=0.43..19.25 rows=198 width=4) (actual time=0.010..0.180 rows=198 loops=1)
NodeSign: 8157818216567004834
Index Cond: (y < 100)
Filter: (z < 100)
-> Index Scan using replan_test_y_idx on replan_test t3 (cost=0.43..19.25 rows=19996 width=4) (actual time=0.009..15.417 rows=20096 loops=1)
NodeSign: 12097487659300777104
Index Cond: (y < 100)
Filter: (z < 100)
Planning Time: 252.050 ms
Execution Time: 32.169 ms
Replan Active: true
Table Entries: 3
Controlled Statements: 1
Replanning Attempts: 3
Final Run Planning Time: 0.612 ms
Total Time Elapsed: 284.219 ms
(29 rows)