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)