G.9. pgpro_temp_stats — сбор статистики по нескольким столбцам временных таблиц #

G.9.1. Описание #

Расширение pgpro_temp_stats собирает расширенную статистику по нескольким столбцам временных таблиц. Оно работает автоматически во время выполнения запросов, которые ссылаются на временные таблицы.

G.9.2. Установка #

Расширение pgpro_temp_stats поставляется вместе с Postgres Pro Enterprise в виде отдельного пакета pgpro-temp-stats-ent-17 (подробные инструкции по установке приведены в Главе 17).

Чтобы включить pgpro_temp_stats, выполните следующие шаги:

  1. Добавьте имя библиотеки в переменную shared_preload_libraries в файле postgresql.conf.

    shared_preload_libraries = 'pgpro_temp_stats'
  2. Перезагрузите сервер баз данных, чтобы изменения вступили в силу.

    Чтобы убедиться, что библиотека pgpro_temp_stats установлена правильно, можно выполнить следующую команду:

    SHOW shared_preload_libraries;
  3. Создайте расширение pgpro_temp_stats, выполнив следующий запрос:

    CREATE EXTENSION pgpro_temp_stats;
  4. Включите расширение, установив для параметра pgpro_temp_stats.enable значение on.

    SET pgpro_temp_stats.enable = 'on';

G.9.3. Использование #

Расширение pgpro_temp_stats автоматически ищет запросы, которые ссылаются на временные таблицы, и собирает необходимые статистические данные. Эти данные позволяют планировщику точнее предсказывать количество строк для таких запросов и сокращать время выполнения.

G.9.3.1. Базовое использование #

pgpro_temp_stats выполняет следующие действия для каждой временной таблицы в запросе:

  1. Выполняет команду CREATE STATISTICS для столбцов, задействованных в запросе.

    Эта команда создаёт объект расширенной статистики с именем, которое имеет следующий формат: stN_имя_таблицы. Информация об этом созданном объекте статистики добавляется в системный каталог pg_statistic_ext, как и для всех прочих объектов статистики.

    Этот шаг выполняется, только если для параметра pgpro_temp_stats.create_statistics установлено значение on (по умолчанию), и запрос ссылается на два или более столбца временной таблицы. Можно установить для этого параметра значение off, чтобы пропускать этот шаг для всех запросов.

  2. Выполняет команду ANALYZE для тех же столбцов, задействованных в запросе.

    Собранные статистические данные добавляются в системный каталог pg_statistic, как и для ручных запусков команды.

Например, для запроса, который ссылается на два столбца одной временной таблицы, действия pgpro_temp_stats выглядят следующим образом:

SELECT * FROM t1 WHERE (a = 1) AND (b = 0);
DEBUG:  CREATE STATISTICS st0_t1 ON a, b FROM t1;
DEBUG:  ANALYZE t1 (a, b)

Расширение pgpro_temp_stats записывает сообщения о его работе в журнал на уровне важности DEBUG1.

Если для параметра pgpro_temp_stats.skip_analyze установлено значение on (по умолчанию), игнорируются все команды ANALYZE, которые запущены по целым временным таблицам автоматически или вручную, пока расширение pgpro_temp_stats включено. Можно установить для этого параметра значение off, чтобы выполнять такие команды в дополнение к операциям pgpro_temp_stats.

G.9.3.2. Использование для соединённых таблиц #

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

SELECT * FROM t2 JOIN t3 ON t2.id = t3.id AND t2.val = t3.val;
DEBUG:  CREATE STATISTICS st0_t2 ON id, val from t2;
DEBUG:  ANALYZE t2 (id, val)
DEBUG:  CREATE STATISTICS st0_t3 ON id, val from t3;
DEBUG:  ANALYZE t3 (id, val)

G.9.3.3. Использование для выражений и функций #

pgpro_temp_stats может также собирать статистику для запросов с предложениями WHERE, которые используют выражения или функции, ссылающиеся на столбцы временных таблиц. В этих случаях pgpro_temp_stats может выполнять команду CREATE STATISTICS как для отдельных столбцов, так и для целых выражений и функций. При этом команда ANALYZE выполняется по столбцам, используемых в выражениях или функциях.

SELECT * FROM t4 WHERE a > 10 AND date_trunc('week', b) = date '2023-05-01';
DEBUG:  CREATE STATISTICS st0_t4 ON a, date_trunc('week', b) from t4;
DEBUG:  ANALYZE t4 (a, b)

G.9.3.4. Хранение обработанных запросов #

pgpro_temp_stats хранит внутри себя идентификаторы запросов, для которых статистические данные уже собраны. Это позволяет pgpro_temp_stats избегать многократного сбора статистики и переиспользовать статистические данные.

Параметр pgpro_temp_stats.ts_max_items указывает максимальное количество хранимых идентификаторов запросов. При достижении этого предела pgpro_temp_stats удаляет идентификаторы из внутреннего хранилища с помощью алгоритма вытеснения давно неиспользуемых данных (Least Recently Used, LRU).

Можно также использовать функцию pgpro_temp_stats_reset, чтобы очистить все идентификаторы запросов в этом внутреннем хранилище.

G.9.4. Пример #

Этот пример демонстрирует принцип работы расширения pgpro_temp_stats.

-- Расширение pgpro_temp_stats отключено

-- Создайте простую временную таблицу
CREATE TEMP TABLE t1 (
    a int,
    b int
);

-- Выполните ANALYZE для целой таблицы
ANALYZE t1;

-- Добавьте данные в созданную таблицу
INSERT INTO t1 SELECT i/100, i/500 FROM generate_series(1, 10000) s(i);

-- Выполните запрос, ссылающийся на два столбца созданной временной таблицы
-- Оценка количества строк гораздо ниже фактического числа строк
EXPLAIN ANALYZE
SELECT * FROM t1 WHERE (a = 1) AND (b = 0);
                                        QUERY PLAN
------------------------------------------------------------------------------------------------
Seq Scan on t1  (cost=0.00..198.22 rows=1 width=8) (actual time=0.059..3.560 rows=100 loops=1)
Filter: ((a = 1) AND (b = 0))
Rows Removed by Filter: 9900
Buffers: local hit=45
Planning:
Buffers: shared hit=24
Planning Time: 0.313 ms
Execution Time: 3.594 ms
(8 rows)

-- Включите расширение pgpro_temp_stats
SET pgpro_temp_stats.enable = true;

-- Настройте сообщения, чтобы видеть информацию о создании статистики и анализе
SET client_min_messages = 'debug1';

-- Выполните тот же запрос. Для столбцов, на которые ссылается этот запрос, pgpro_temp_stats
-- автоматически создаёт объект расширенной статистики и запускает ANALYZE
-- В результате оценка количества строк становится точнее
EXPLAIN ANALYZE
SELECT * FROM t1 WHERE (a = 1) AND (b = 0);
DEBUG:  CREATE STATISTICS st0_t1 ON a, b FROM t1;
DEBUG:  ANALYZE t1 (a, b)
                                            QUERY PLAN
--------------------------------------------------------------------------------------------------
Seq Scan on t1  (cost=0.00..195.00 rows=100 width=8) (actual time=0.090..2.981 rows=100 loops=1)
Filter: ((a = 1) AND (b = 0))
Rows Removed by Filter: 9900
Buffers: local hit=45
Planning:
Buffers: shared hit=143 dirtied=6 written=6, local hit=45
Planning Time: 12.958 ms
Execution Time: 3.009 ms
(8 rows)

G.9.5. Параметры конфигурации #

pgpro_temp_stats.enable (boolean) #

Включает или отключает расширение pgpro_temp_stats. Значение по умолчанию — off. Изменить этот параметр могут только суперпользователи.

pgpro_temp_stats.create_statistics (boolean) #

Указывает, запускать ли команду CREATE STATISTICS автоматически для столбцов временных таблиц, задействованных в запросах. Значение по умолчанию — on. Изменить этот параметр могут только суперпользователи.

pgpro_temp_stats.skip_analyze (boolean) #

Указывает, игнорировать ли команды ANALYZE, которые запущены по целым временным таблицам автоматически или вручную, пока расширение pgpro_temp_stats включено. Значение по умолчанию — on. Изменить этот параметр могут только суперпользователи.

pgpro_temp_stats.ts_max_items (integer) #

Указывает максимальное количество хранимых идентификаторов запросов, ссылающихся на временные таблицы, для которых статистические данные уже собраны. Значение по умолчанию — 4096.

G.9.6. Функции #

pgpro_temp_stats_reset() returns bigint #

Удаляет все хранимые идентификаторы запросов, ссылающихся на временные таблицы, для которых статистические данные уже собраны. Возвращает количество удалённых записей.

FAQ