75.1. Как это работает #

Если во время выполнения запроса сработал триггер перепланирования, начнётся перепланирование этого запроса. Частично выполненный запрос игнорируется, и предпринимается попытка собрать информацию для дальнейшего перепланирования. Если полезная информация не найдена, выполнение запроса начинается сначала, но без активированных триггеров перепланирования. Информация об операторе запроса и оценке количества строк узлов сохраняется. Информация об узлах сохраняется для:

  • Непараметризованных узлов

  • Параметризованных узлов, фактическая мощность которых больше используемой планировщиком

Перепланирование продолжается до тех пор, пока не выполнено условие триггера или не превышено настроенное максимальное количество попыток перепланирования, либо пока находится новая информация. Максимальное количество попыток перепланирования определяется параметром конфигурации replan_max_attempts.

Если триггер перепланирования активирован, запрос, соответствующий условию триггера, выполняется в неявно созданной подтранзакции. В случае перепланирования это помогает выполнять очистку после предыдущего запроса и освобождать системные ресурсы, такие как память или дисковое пространство.

75.1.1. Триггеры перепланирования #

Следующие триггеры могут прервать запрос и запустить перепланирование:

  • Время выполнения запроса: триггер срабатывает при выполнении запроса дольше указанного времени. Значение определяется параметром конфигурации replan_query_execution_time.

  • Количество обработанных кортежей узлов: триггер срабатывает, когда количество таких кортежей превышает число, обычно ожидаемое планировщиком, которое умножается на значение параметра конфигурации replan_overrun_limit.

75.1.2. Просмотр подробностей о перепланировании #

Если параметр replan_show_signature включён, информация, связанная с перепланированием, добавляется в вывод команды EXPLAIN ANALYZE. Раздел SUMMARY дополнительно включает следующие характеристики:

  • Replan Active — срабатывал ли триггер перепланирования во время выполнения запроса.

  • Table Entries — количество таблиц в запросе, включая подзапросы.

  • Controlled Statements — количество операторов, которые были перепланированы во время выполнения запроса.

  • Replanning Attempts — общее количество перезапусков/попыток перепланирования запроса.

  • Total Execution Time — общее время выполнения запроса, включая время всех попыток перезапуска/перепланирования.

Для каждого узла плана включены следующие характеристики:

  • NodeSign — 64-битная подпись (хеш) узла, которая однозначно идентифицирует узел плана запроса. Подписаны не все узлы, а только те, где ошибки модели оценки оптимизатора могут приводить к ошибкам в поиске оптимального плана запроса.

  • Cardinality — количество кортежей узла плана, достигнутое при предыдущих выполнениях запроса. Доступно только с параметром VERBOSE.

  • Groups Number — количество групп, вычисленное для этого узла плана в результате предыдущих выполнений запроса. Доступно только с параметром VERBOSE.

75.1.3. Пример #

Пример 75.1. Использование перепланирования

В следующем примере показано использование перепланирования:

    SET replan_show_signature = 'on';
    SET replan_query_execution_time = 10;
    SET replan_enable = 'on';

    DROP TABLE IF EXISTS replan_test CASCADE;
    CREATE TABLE replan_test WITH (autovacuum_enabled = off) AS
    SELECT 1 AS x, 'abc' AS payload FROM generate_series(1,1E4);
    ANALYZE replan_test;

    INSERT INTO replan_test (x,payload) (
    SELECT gs, repeat('a', 256)
    FROM generate_series(1,100) AS gs);


  EXPLAIN ANALYZE VERBOSE
  SELECT count(*) FROM (
  SELECT q2.x,q2.payload, max(q2.x) FROM (
  SELECT rt1.x, rt1.payload
  FROM replan_test rt1
  ) AS q2
  GROUP BY (q2.x,q2.payload) HAVING avg(q2.x) > 30
  ) AS q1, replan_test rt2
  WHERE q1.x=rt2.x
  ;
  

Результат:

  Aggregate  (cost=560.06..560.07 rows=1 width=8) (actual time=4.705..4.707 rows=1 loops=1)
  NodeSign: 4127104911444856927
  Cardinality: -1
  Groups Number: -1
  Output: count(*)
  ->  Hash Join  (cost=232.05..533.39 rows=10667 width=0) (actual time=4.681..4.701 rows=70 loops=1)
      NodeSign: 15478158356720060206
      Cardinality: -1
      Groups Number: -1
      Hash Cond: (rt2.x = q1.x)
      ->  Seq Scan on public.replan_test rt2  (cost=0.00..154.67 rows=10667 width=4) (actual time=0.007..0.785 rows=10100 loops=1)
            NodeSign: 17491169463296369090
            Cardinality: -1
            Groups Number: -1
            Output: rt2.x, rt2.payload
      ->  Hash  (cost=231.99..231.99 rows=5 width=4) (actual time=3.083..3.084 rows=70 loops=1)
            NodeSign: 17790666881744499777
            Output: q1.x
            Buckets: 1024  Batches: 1  Memory Usage: 11kB
            ->  Subquery Scan on q1  (cost=230.42..231.99 rows=5 width=4) (actual time=3.026..3.073 rows=70 loops=1)
                  NodeSign: 17790666881744499777
                  Output: q1.x
                  ->  HashAggregate  (cost=230.42..231.94 rows=5 width=12) (actual time=3.025..3.065 rows=70 loops=1)
                        NodeSign: 13744336777062894583
                        Cardinality: 5
                        Groups Number: 101
                        Output: rt1.x, rt1.payload, NULL::integer
                        Group Key: rt1.x, rt1.payload
                        Filter: (avg(rt1.x) > '30'::numeric)
                        Batches: 1  Memory Usage: 80kB
                        Rows Removed by Filter: 31
                        ->  Seq Scan on public.replan_test rt1  (cost=0.00..154.67 rows=10100 width=8) (actual time=0.004..0.865 rows=10100 loops=1)
                              NodeSign: 14925644762129093451
                              Cardinality: 10100
                              Groups Number: -1
                              Output: rt1.x, rt1.payload
  Planning Time: 0.135 ms
  Execution Time: 4.746 ms
  Replan Active: true
  Table Entries: 2
  Controlled Statements: 1
  Replanning Attempts: 1
  Total Execution Time: 15.530 ms