76.1. Как это работает #
Если во время выполнения запроса сработал триггер перепланирования, начнётся перепланирование этого запроса. Частично выполненный запрос игнорируется, и предпринимается попытка собрать информацию для дальнейшего перепланирования. Если полезная информация не найдена, выполнение запроса начинается сначала, но без активированных триггеров перепланирования. Информация об операторе запроса и оценке количества строк узлов сохраняется. Информация об узлах сохраняется для:
Непараметризованных узлов
Параметризованных узлов, фактическая мощность которых больше используемой планировщиком
Перепланирование продолжается до тех пор, пока не выполнено условие триггера или не превышено настроенное максимальное количество попыток перепланирования, либо пока находится новая информация. Максимальное количество попыток перепланирования определяется параметром конфигурации replan_max_attempts.
Если триггер перепланирования активирован, запрос, соответствующий условию триггера, выполняется в неявно созданной подтранзакции. В случае перепланирования это помогает выполнять очистку после предыдущего запроса и освобождать системные ресурсы, такие как память или дисковое пространство.
76.1.1. Триггеры перепланирования #
Следующие триггеры могут прервать запрос и запустить перепланирование:
Время выполнения запроса: триггер срабатывает, если запрос выполняется дольше, чем указано в параметре конфигурации replan_query_execution_time.
Количество обработанных кортежей узлов: триггер срабатывает, когда количество таких кортежей превышает число, обычно ожидаемое планировщиком, которое умножается на значение параметра конфигурации replan_overrun_limit.
Потребление памяти рабочим процессом: триггер срабатывает, когда потребление памяти рабочим процессом превышает значение параметра конфигурации replan_memory_limit и срабатывает триггер количества обработанных кортежей узлов.
76.1.2. Просмотр подробностей о перепланировании #
Если параметр replan_show_signature включён, информация, связанная с перепланированием, добавляется в вывод команды EXPLAIN ANALYZE
. Раздел SUMMARY
дополнительно включает следующие характеристики:
Replan Active
— срабатывал ли триггер перепланирования во время выполнения запроса.Table Entries
— количество таблиц в запросе, включая подзапросы.Controlled Statements
— количество операторов, которые были перепланированы во время выполнения запроса.Replanning Attempts
— общее количество перезапусков/попыток перепланирования запроса.Total Time Elapsed
— общее время выполнения запроса, включая время всех попыток перезапуска/перепланирования. Это свойство отображается только в том случае, если запрос был переоптимизирован и перезапущен хотя бы один раз.Final Run Planning Time
— время планирования последней переоптимизации при перепланировании. Это свойство отображается только в том случае, если запрос был переоптимизирован и перезапущен хотя бы один раз.
Для каждого узла плана включены следующие характеристики:
NodeSign
— 64-битная подпись (хеш) узла, которая однозначно идентифицирует узел плана запроса. Подписаны не все узлы, а только те, где ошибки модели оценки оптимизатора могут приводить к ошибкам в поиске оптимального плана запроса.Cardinality
— количество кортежей узла плана, достигнутое при предыдущих выполнениях запроса. Доступно только с параметромVERBOSE
.Groups Number
— количество групп, вычисленное для этого узла плана в результате предыдущих выполнений запроса. Доступно только с параметромVERBOSE
.
76.1.3. Пример #
Пример 76.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)