G.4. pgpro_multiplan — сохранение планов выполнения запросов для последующего использования #
- G.4.1. Описание
- G.4.2. Установка
- G.4.3. Поддерживаемые режимы и типы планов
- G.4.4. Идентификация планов
- G.4.5. Заморозка планов
- G.4.6. Захват и одобрение планов
- G.4.7. Резервное копирование и восстановление планов
- G.4.8. Совместимость с другими расширениями
- G.4.9. Автоматическое приведение типов
- G.4.10. Статистика использования планов
- G.4.11. Интеграция с AQE
- G.4.12. Представления
- G.4.13. Функции
- G.4.14. Параметры конфигурации
- G.4.2. Установка
G.4.1. Описание #
Расширение pgpro_multiplan позволяет сохранять планы выполнения запросов и использовать их при последующем выполнении тех же запросов, что помогает избежать повторной оптимизации идентичных запросов. Можно также использовать это расширение для фиксации определённого плана выполнения, если план, выбранный планировщиком, по каким-то причинам не подходит. pgpro_multiplan работает подобно Oracle SQL Plan Management (управление SQL-планами).
G.4.2. Установка #
Расширение pgpro_multiplan предоставляется вместе с Postgres Pro Enterprise в виде отдельного пакета pgpro-multiplan-ent-17 (подробные инструкции по установке приведены в Главе 17). Чтобы включить pgpro_multiplan, выполните следующие действия:
Добавьте имя библиотеки в переменную
shared_preload_librariesв файлеpostgresql.conf:shared_preload_libraries = 'pgpro_multiplan'
Обратите внимание, что имена библиотек в переменной
shared_preload_librariesдолжны добавляться в определённом порядке. Совместимость pgpro_multiplan с другими расширениями описана в Подразделе G.4.8.Перезагрузите сервер баз данных, чтобы изменения вступили в силу.
Чтобы убедиться, что библиотека
pgpro_multiplanустановлена правильно, вы можете выполнить следующую команду:SHOW shared_preload_libraries;
Создайте расширение pgpro_multiplan, выполнив следующий запрос:
CREATE EXTENSION pgpro_multiplan;
Расширение pgpro_multiplan использует кеш разделяемой памяти, который инициализируется только при запуске сервера, поэтому данная библиотека также должна предзагружаться при запуске. Расширение pgpro_multiplan следует создать в каждой базе данных, где требуется управление запросами.
Включите расширение pgpro_multiplan, которое выключено по умолчанию. Для этого укажите необходимые режимы в параметре pgpro_multiplan.mode. За дополнительной информацией обратитесь к разделу Поддерживаемые режимы и типы планов.
Включить pgpro_multiplan можно одним из следующих способов:
Чтобы активировать расширение для всех сеансов, задайте параметр
pgpro_multiplan.modeв файлеpostgresql.conf.Чтобы активировать расширение в текущем сеансе, используйте следующую команду:
SET pgpro_multiplan.mode = 'frozen';
При необходимости переноса данных pgpro_multiplan с главного на резервный сервер при помощи физической репликации, на обоих серверах необходимо задать значение параметра pgpro_multiplan.wal_rw=
on. Также убедитесь, что на обоих серверах установлена одинаковая версия pgpro_multiplan, иначе репликация может работать некорректно.
G.4.3. Поддерживаемые режимы и типы планов #
Расширение pgpro_multiplan предоставляет следующие типы планов:
Замороженные планы
Зафиксированные планы, которым отдаётся приоритет при выполнении соответствующих запросов. Запрос может иметь только один замороженный план.
pgpro_multiplan поддерживает следующие типы замороженных планов:
Сериализованные планы
Сериализованные представления планов. Эти планы преобразуются в выполняемые планы при первом выполнении соответствующих запросов.
Сериализованные планы остаются действительными до тех пор, пока не изменятся метаданные запроса (такие как структуры таблиц, индексы и так далее). Например, если таблица, задействованная в плане, пересоздаётся, то этот план становится недействительным и игнорируется. Сериализованные планы действительны только в текущей базе данных и не могут быть скопированы в другую, поскольку они зависят от идентификаторов объектов (OID). По этой причине использовать сериализованные планы для временных таблиц не имеет смысла.
Планы с наборами указаний
Наборы указаний, которые формируются на основе соответствующих планов выполнения в момент заморозки. Набор указаний включает типы соединений, порядок соединений, методы доступа к данным и переменные окружения оптимизатора, значения которых отличаются от используемых по умолчанию. Эти указания соответствуют указаниям, которые поддерживаются расширением pg_hint_plan. Таким образом, для использования планов с наборами указаний необходимо включить расширение pg_hint_plan.
Если найден соответствующий замороженный запрос, указания передаются pg_hint_plan для генерации выполняемого плана. Если расширение pg_hint_plan отключено, указания игнорируются и используется план, сформированный оптимизатором Postgres Pro. Планы с наборами указаний не зависят от идентификаторов объектов (OID) и остаются действительным при пересоздании таблиц, добавлении полей и других изменениях.
Планы с шаблонами
Эти планы похожи на замороженные планы с наборами указаний, но используют шаблоны для имён таблиц. Если у запроса нет соответствующего замороженного плана, pgpro_multiplan пытается найти для этого запроса подходящий план с шаблонами.
Эти планы тоже основаны на наборах указаний и требуют, чтобы расширение pg_hint_plan было включено. Однако такие планы могут применяться только для запросов с именами таблиц, которые соответствуют регулярному выражению POSIX, указанному в параметре pgpro_multiplan.wildcards. Значение
pgpro_multiplan.wildcardsзамораживается вместе с соответствующим запросом. Если расширение pg_hint_plan отключено, указания игнорируются и используется план, сформированный оптимизатором Postgres Pro.Базовые планы
Наборы разрешённых планов, которые могут использоваться для выполнения запросов, если для них отсутствуют соответствующие замороженные планы или планы с шаблонами.
Как и замороженные планы с наборами указаний, базовые планы основаны на наборах указаний и требуют, чтобы расширение pg_hint_plan было включено. Если расширение pg_hint_plan отключено, указания игнорируются и используется план, сформированный оптимизатором Postgres Pro.
Используйте параметр конфигурации pgpro_multiplan.mode для указания списка включённых режимов и типов планов в, разделённых запятыми. По умолчанию для этого параметра указана пустая строка, означающая, что все режимы планов выключены.
G.4.4. Идентификация планов #
В зависимости от типа планы идентифицируются следующими способами:
Замороженные планы (и сериализованные, и с наборами указаний) идентифицируются по комбинации
sql_hashиconst_hash.sql_hashвычисляется на основе дерева разбора без учёта параметров и констант. Псевдонимы полей и таблиц не игнорируются, поэтому одинаковые запросы с разными псевдонимами будут иметь разные значенияsql_hash.const_hashвычисляется на основе всех констант, использующихся в запросе. Даже если значения констант совпадают, но типы данных различаются (например,1и'1'), значения хеша будут разными.Планы с шаблонами идентифицируются по комбинации
sql_hashиtable_hash.sql_hashвычисляется на основе дерева разбора без учёта имён таблиц, параметров и констант.table_hashвычисляется на основе имён таблиц, которые не соответствуют регулярному выражению, указанному в параметре pgpro_multiplan.wildcards.const_hashдля этих планов всегда равен0.Базовые планы идентифицируются по комбинации
sql_hashиplan_hash.sql_hashвычисляется так же, как и для замороженных планов.plan_hash— это внутренний идентификатор плана.const_hashдля этих планов всегда равен0.
G.4.5. Заморозка планов #
Чтобы заморозить определённые планы выполнения запроса для дальнейшего использования, выполните следующие шаги:
Используйте параметр pgpro_multiplan.mode, чтобы указать разделённый запятыми список с типами планов, которые будут создаваться. За подробной информацией о типах планов обратитесь к разделу Поддерживаемые режимы и типы планов.
SET pgpro_multiplan.mode = 'frozen, wildcards, baseline, statistics';
Зарегистрируйте запрос, для которого нужно зафиксировать план, одним из следующих способов:
Используйте функцию pgpro_multiplan_register_query, чтобы зарегистрировать запрос вручную.
SELECT pgpro_multiplan_register_query(
query_string,parameter_type, ...);Здесь
query_string— запрос с параметрами$(аналогичноnPREPARE). Можно описать каждый тип параметра, используя необязательный аргумент функцииstatement_nameASparameter_type, или отказаться от явного определения типов параметров. В последнем случае Postgres Pro пытается определить тип каждого параметра из контекста. Эта функция возвращает уникальную паруsql_hashиconst_hash. После этого pgpro_multiplan будет отслеживать выполнение запросов, соответствующих сохранённому шаблону параметризованного запроса.-- Создайте таблицу 'a' CREATE TABLE a AS (SELECT * FROM generate_series(1,30) AS x); CREATE INDEX ON a(x); ANALYZE; -- Зарегистрируйте запрос SELECT sql_hash, const_hash FROM pgpro_multiplan_register_query('SELECT count(*) FROM a WHERE x = 1 OR (x > $2 AND x < $1) OR x = $1', 'int', 'int'); sql_hash | const_hash -----------------------+------------- -6037606140259443514 | 2413041345 (1 row)Обратите внимание, что при регистрации подготовленного оператора номера и позиции параметров в параметризованном шаблоне запроса должны совпадать с номерами и позициями параметров в подготовленном операторе. В противном случае шаблон игнорируется.
Установите для параметра pgpro_multiplan.auto_tracking значение
on, чтобы автоматически регистрировать запросы, выполняемые с помощью командEXPLAINиEXPLAIN EXECUTE.-- Включите pgpro_multiplan.auto_tracking SET pgpro_multiplan.auto_tracking = on; -- Выполните EXPLAIN для непараметризованного запроса EXPLAIN SELECT count(*) FROM a WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22; Custom Scan (MultiplanScan) (cost=1.60..0.00 rows=1 width=8) Plan is: tracked SQL hash: 5393873830515778388 Const hash: 0 Plan hash: 0 -> Aggregate (cost=1.60..1.61 rows=1 width=8) -> Seq Scan on a (cost=0.00..1.60 rows=2 width=0) Filter: ((x = $1) OR ((x > $2) AND (x < $3)) OR (x = $4)) -- Отключите pgpro_multiplan.auto_tracking SET pgpro_multiplan.auto_tracking = off;
Измените план выполнения запроса, если необходимо. Это можно сделать с помощью параметров конфигурации, указаний расширения pg_hint_plan, если оно включено, или других расширений, которые позволяют изменять план запроса, например aqo. За информацией о совместимости pgpro_multiplan с этими расширениями обратитесь к разделу Совместимость с другими расширениями.
Заморозьте план выполнения запроса с помощью функции pgpro_multiplan_freeze. Для необязательного аргумента
plan_typeукажите значениеserialized,hintset,templateилиbaselineв зависимости от типа плана, который нужно создать. Если этот аргумент опущен, по умолчанию используетсяserialized.SELECT pgpro_multiplan_freeze('serialized'); pgpro_multiplan_freeze ------------------------ t (1 row)Если создаётся план с набором указаний, план с шаблоном или разрешённый план, включите расширение pg_hint_plan. За подробной информацией обратитесь к разделу Совместимость с другими расширениями.
Если создаётся план с шаблоном, используйте параметр pgpro_multiplan.wildcards, чтобы указать регулярное выражение POSIX, используемое для проверки соответствия имён таблиц, задействованных в запросах.
Доступ ко всем зафиксированным планам можно получить в представлении pgpro_multiplan_storage.
G.4.5.1. Пример добавления замороженного плана #
Пример ниже показывает, как добавить замороженный план.
-- Выполните запрос и проверьте его план
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM a
WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22;
QUERY PLAN
-------------------------------------------------------------------------
Aggregate (actual rows=1 loops=1)
-> Seq Scan on a (actual rows=12 loops=1)
Filter: ((x = 1) OR ((x > 11) AND (x < 22)) OR (x = 22))
Rows Removed by Filter: 18
Planning Time: 0.179 ms
Execution Time: 0.069 ms
(6 rows)
-- Разрешите использование замороженных планов
SET pgpro_multiplan.mode = 'frozen';
-- Зарегистрируйте запрос
SELECT sql_hash, const_hash
FROM pgpro_multiplan_register_query('SELECT count(*) FROM a
WHERE x = 1 OR (x > $2 AND x < $1) OR x = $1', 'int', 'int');
sql_hash | const_hash
----------------------+------------
-6037606140259443514 | 2413041345
(1 row)
-- Измените план выполнения запроса
-- Запустите сканирование индекса, отключив последовательное сканирование
SET enable_seqscan = 'off';
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM a
WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22;
QUERY PLAN
----------------------------------------------------------------------------
Custom Scan (MultiplanScan) (actual rows=1 loops=1)
Plan is: tracked
SQL hash: -6037606140259443514
Const hash: 2413041345
Plan hash: 0
-> Aggregate (actual rows=1 loops=1)
-> Index Only Scan using a_x_idx on a (actual rows=12 loops=1)
Filter: ((x = 1) OR ((x > $2) AND (x < $1)) OR (x = $1))
Rows Removed by Filter: 18
Heap Fetches: 30
Planning Time: 0.235 ms
Execution Time: 0.099 ms
(12 rows)
-- Снова включите последовательное сканирование
RESET enable_seqscan;
-- Заморозьте план выполнения запроса
SELECT pgpro_multiplan_freeze();
pgpro_multiplan_freeze
------------------------
t
(1 row)
-- Теперь замороженный план используется со сканированием индекса
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM a
WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22;
QUERY PLAN
----------------------------------------------------------------------------
Custom Scan (MultiplanScan) (actual rows=1 loops=1)
Plan is: frozen, serialized
SQL hash: -6037606140259443514
Const hash: 2413041345
Plan hash: 0
-> Aggregate (actual rows=1 loops=1)
-> Index Only Scan using a_x_idx on a (actual rows=12 loops=1)
Filter: ((x = 1) OR ((x > $2) AND (x < $1)) OR (x = $1))
Rows Removed by Filter: 18
Heap Fetches: 30
Planning Time: 0.063 ms
Execution Time: 0.119 ms
(12 rows)G.4.5.2. Пример добавления набора базовых планов #
Пример ниже показывает, как создать набор базовых планов.
-- Создайте таблицу 'a'
CREATE TEMP TABLE a AS (SELECT * FROM generate_series(1,1000) AS x);
CREATE INDEX ON a(x);
ANALYZE;
-- Разрешите использование базовых планов
SET pgpro_multiplan.mode = 'baseline';
-- Зарегистрируйте запрос
SELECT sql_hash sql_hash, const_hash const_hash
FROM pgpro_multiplan_register_query('SELECT count(*) FROM a WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22');
sql_hash | const_hash
-----------------------+-------------
-6037606140259443514 | 2413041345
(1 row)
-- Проверьте план выполнения запроса
EXPLAIN SELECT count(*) FROM a WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22;
QUERY PLAN
------------------------------------------------------------
Custom Scan (MultiplanScan) (actual rows=1 loops=1)
Plan is: tracked
Hint string: BitmapScan("a" "a_x_idx")
-> Aggregate (actual rows=1 loops=1)
-> Bitmap Heap Scan on a (actual rows=12 loops=1)
(5 rows)
-- Добавьте план выполнения запроса в набор базовых планов
SELECT pgpro_multiplan_freeze('baseline');
pgpro_multiplan_freeze
------------------------
t
(1 row)
-- Теперь можно увидеть добавленный план с помощью соответствующего представления
SELECT * FROM pgpro_multiplan_storage \gx
-[ RECORD 1 ]-+---------------------------------------------------------------------
dbid | 5
sql_hash | -6037606140259443514
const_hash | 0
plan_hash | 487722818968417375
valid | t
cost | 36.785
sample_string | SELECT count(*) FROM a WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22
query_string | SELECT count(*) FROM a WHERE x = $1 OR (x > $2 AND x < $3) OR x = $4
paramtypes |
query | <>
plan_type | baseline
plan | <>
hintstr | BitmapScan("a" "a_x_idx")
wildcards |
-- План из набора базовых планов теперь применяется при выполнении соотвествующего запроса
SET enable_bitmapscan = FALSE;
EXPLAIN SELECT count(*) FROM a WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22;
QUERY PLAN
------------------------------------------------------------
Custom Scan (MultiplanScan) (actual rows=1 loops=1)
Plan is: baseline
Hint string: BitmapScan("a" "a_x_idx")
-> Aggregate (actual rows=1 loops=1)
-> Bitmap Heap Scan on a (actual rows=12 loops=1)
(5 rows)
RESET enable_bitmapscan;G.4.5.3. Примеры заморозки планов для подготовленных операторов #
В примере ниже показано, как зарегистрировать подготовленный оператор с помощью функции pgpro_multiplan_register_query и заморозить план выполнения оператора.
-- Создайте таблицу 'a'
CREATE TABLE a AS (SELECT * FROM generate_series(1,30) AS x);
CREATE INDEX ON a(x);
ANALYZE;
-- Создайте подготовленный оператор
PREPARE stmt AS SELECT count(*) FROM a
WHERE x = $2 OR x < $1 OR x = 10;
-- Зарегистрируйте оператор. Обратите внимание, что номера и позиции параметров $1 и $2
-- в параметризованном шаблоне запроса совпадают с номерами и позициями параметров
-- в подготовленном операторе
SELECT sql_hash, const_hash
FROM pgpro_multiplan_register_query('SELECT count(*) FROM a
WHERE x = $2 OR x < $1 OR x = $3');
-- Выполните подготовленный оператор с параметрами
EXPLAIN (COSTS OFF, TIMING OFF) EXECUTE stmt(10, 1);
QUERY PLAN
----------------------------------------------------------
Custom Scan (MultiplanScan)
Plan is: tracked
SQL hash: -1476198425806211485
Const hash: 0
Plan hash: 0
-> Aggregate
-> Seq Scan on a
Filter: ((x = $2) OR (x < $1) OR (x = $3))
(8 rows)
-- Заморозьте план выполнения оператора
SELECT pgpro_multiplan_freeze();
-- Выполните оператор ещё раз. Используется замороженный план
EXPLAIN (COSTS OFF, TIMING OFF) EXECUTE stmt(10, 1);
QUERY PLAN
----------------------------------------------------------
Custom Scan (MultiplanScan)
Plan is: frozen, serialized
SQL hash: -1476198425806211485
Const hash: 0
Plan hash: 0
-> Aggregate
-> Seq Scan on a
Filter: ((x = $2) OR (x < $1) OR (x = $3))
(8 rows)В следующем примере показано, как автоматически зарегистрировать выполняемый подготовленный оператор.
-- Создайте подготовленный оператор
PREPARE stmt AS SELECT count(*) FROM a
WHERE x = $2 OR x < $1 OR x = 10;
-- Включите автоматическую регистрацию выполняемых операторов
SET pgpro_multiplan.auto_tracking = on;
-- Выполните подготовленный оператор с параметрами
EXPLAIN (COSTS OFF, TIMING OFF) EXECUTE stmt(10, 1);
QUERY PLAN
----------------------------------------------------------
Custom Scan (MultiplanScan)
Plan is: tracked
SQL hash: -1476198425806211485
Const hash: 0
Plan hash: 0
-> Aggregate
-> Seq Scan on a
Filter: ((x = $2) OR (x < $1) OR (x = $3))
(8 rows)
-- Отключите автоматическую регистрацию
SET pgpro_multiplan.auto_tracking = off;
-- Заморозьте план выполнения оператора
SELECT pgpro_multiplan_freeze();G.4.6. Захват и одобрение планов #
Планы можно также добавлять в набор базовых планов, выполняя следующие шаги:
Укажите для параметра pgpro_multiplan.mode значение
baseline.Включите расширение pg_hint_plan. За подробной информацией обратитесь к разделу Совместимость с другими расширениями.
Укажите для параметра pgpro_multiplan.auto_capturing значение
on, чтобы включить захват всех выполняемых запросов. Получить доступ к этим захваченным запросам можно в представлении pgpro_multiplan_captured_queries.Одобрите любой захваченный план с помощью функции pgpro_multiplan_captured_approve с указанными аргументами
dbid,sql_hashиplan_hash.Установите для параметра pgpro_multiplan.auto_capturing значение
offпосле завершения захвата.
-- Создайте таблицу 'a'
CREATE TABLE a AS SELECT x, x AS y FROM generate_series(1,1000) x;
CREATE INDEX ON a(x);
CREATE INDEX ON a(y);
ANALYZE;
-- Разрешите использование базовых планов и включите автоматический захват
SET pgpro_multiplan.mode = 'baseline'
SET pgpro_multiplan.auto_capturing = 'on';
-- Выполните запрос
SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 1000 AND t2.y > 900;
count
-------
100
(1 row)
-- Выполните запрос ещё раз с другими константами, чтобы получить другой план
SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 10 AND t2.y > 900;
count
-------
0
(1 row)
-- Теперь захваченные планы можно увидеть в соответствующем представлении
SELECT * FROM pgpro_multiplan_captured_queries \gx
dbid | 5
sql_hash | 6079808577596655075
plan_hash | -487722818968417375
queryid | -8984284243102644350
cost | 36.785
sample_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 1000 AND t2.y > 900;
query_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= $1 AND t2.y > $2;
hint_str | Leading(("t1" "t2" )) HashJoin("t1" "t2") IndexScan("t2" "a_y_idx") SeqScan("t1")
explain_plan | Aggregate (cost=36.77..36.78 rows=1 width=8)
| Output: count(*)
| -> Hash Join (cost=11.28..36.52 rows=100 width=0)
| Hash Cond: (t1.x = t2.x)
| -> Seq Scan on public.a t1 (cost=0.00..20.50 rows=1000 width=4)
| Output: t1.x, t1.y
| Filter: (t1.y <= 1000)
| -> Hash (cost=10.03..10.03 rows=100 width=4)
| Output: t2.x
| Buckets: 1024 Batches: 1 Memory Usage: 12kB
| -> Index Scan using a_y_idx on public.a t2 (cost=0.28..10.03 rows=100 width=4)
| Output: t2.x
| Index Cond: (t2.y > 900)
| Query Identifier: -8984284243102644350
|
-[ RECORD 2 ]-+-----------------------------------------------------------------------------------------------------
dbid | 5
sql_hash | 6079808577596655075
plan_hash | 2719320099967191582
queryid | -8984284243102644350
cost | 18.997500000000002
sample_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 10 AND t2.y > 900;
query_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= $1 AND t2.y > $2;
hint_str | Leading(("t2" "t1" )) HashJoin("t1" "t2") IndexScan("t2" "a_y_idx") IndexScan("t1" "a_y_idx")
explain_plan | Aggregate (cost=18.99..19.00 rows=1 width=8)
| Output: count(*)
| -> Hash Join (cost=8.85..18.98 rows=1 width=0)
| Hash Cond: (t2.x = t1.x)
| -> Index Scan using a_y_idx on public.a t2 (cost=0.28..10.03 rows=100 width=4)
| Output: t2.x, t2.y
| Index Cond: (t2.y > 900)
| -> Hash (cost=8.45..8.45 rows=10 width=4)
| Output: t1.x
| Buckets: 1024 Batches: 1 Memory Usage: 9kB
| -> Index Scan using a_y_idx on public.a t1 (cost=0.28..8.45 rows=10 width=4)
| Output: t1.x
| Index Cond: (t1.y <= 10)
| Query Identifier: -8984284243102644350
|
-- Отключите автоматический захват. Это не повлияет на планы, которые были захвачены ранее
SET pgpro_multiplan.auto_capturing = 'off';
-- Вручную одобрите план со сканированием индекса
SELECT pgpro_multiplan_captured_approve(5, 6079808577596655075, 2719320099967191582);
pgpro_multiplan_captured_approve
----------------------------------
t
(1 row)
-- Или одобрите планы, выбранные из списка захваченных планов
SELECT pgpro_multiplan_captured_approve(dbid, sql_hash, plan_hash)
FROM pgpro_multiplan_captured_queries
WHERE query_string like '%SELECT % FROM a t1, a t2%';
pgpro_multiplan_captured_approve
----------------------------------
t
(1 row)
-- Одобренные планы автоматически удаляются из хранилища захваченных планов
SELECT count(*) FROM pgpro_multiplan_captured_queries;
count
-------
0
(1 row)
-- Одобренные планы можно увидеть в представлении pgpro_multiplan_storage
SELECT * FROM pgpro_multiplan_storage \gx
-[ RECORD 1 ]-+------------------------------------------------------------------------------------------------
dbid | 5
sql_hash | 6079808577596655075
const_hash | 0
plan_hash | -487722818968417375
valid | t
cost | 36.785
sample_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 1000 AND t2.y > 900;
query_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= $1 AND t2.y > $2;
paramtypes |
query | <>
plan | <>
plan_type | baseline
hintstr | Leading(("t1" "t2" )) HashJoin("t1" "t2") IndexScan("t2" "a_y_idx") SeqScan("t1")
wildcards |
-[ RECORD 2 ]-+------------------------------------------------------------------------------------------------
dbid | 5
sql_hash | 6079808577596655075
const_hash | 0
plan_hash | 2719320099967191582
valid | t
cost | 18.997500000000002
sample_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 10 AND t2.y > 900;
query_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= $1 AND t2.y > $2;
paramtypes |
query | <>
plan | <>
plan_type | baseline
hintstr | Leading(("t2" "t1" )) HashJoin("t1" "t2") IndexScan("t2" "a_y_idx") IndexScan("t1" "a_y_idx")
wildcards |G.4.7. Резервное копирование и восстановление планов #
Расширение pgpro_multiplan позволяет создавать резервные копии необходимых планов и затем восстанавливать эти планы в текущую базу данных. Это может быть полезно для переноса планов между базами данных или экземплярами серверов.
Чтобы создать резервную копию планов из определённой базы данных, используйте представление pgpro_multiplan_storage следующим образом:
CREATE TABLE storage_copy AS SELECT s.* FROM pgpro_multiplan_storage s JOIN pg_database d ON s.dbid = d.oid WHERE d.datname = 'db_name';
Чтобы восстановить планы из резервной копии, вызовите функцию pgpro_multiplan_restore, например, следующим образом:
SELECT s.query_string, res.sql_hash IS NOT NULL AS success FROM storage_copy s, LATERAL pgpro_multiplan_restore(s.query_string, s.sample_string, s.hintstr, s.paramtypes, s.plan_type, s.wildcards, NULL) res;
Примечание
Планы могут быть восстановлены только при работающем расширении pg_hint_plan, см. раздел Совместимость с другими расширениями.
G.4.7.1. Особенности и ограничения #
При создании резервных копий и восстановлении планов обратите внимание на следующие особенности и ограничения:
Планы всегда восстанавливаются в текущую базу данных. Чтобы восстановить планы в другую базу данных, сначала подключитесь к ней. Таким образом, рекомендуется создавать резервные копии планов только из одной базы данных, как для
db_nameв примерах в этой секции. Если нужно перенести планы для нескольких баз данных, создайте для них отдельные резервные копии, подключитесь последовательно к каждой целевой базе данных и восстановите планы из соответствующих резервных копий.Если копия планов создаётся из нескольких баз данных, и эти базы данных содержат разные планы для одинаковых запросов, восстанавливается только первый конфликтующий план.
Можно восстановить только планы для допустимых запросов, что означает, что все отношения, используемые в запросе, должны существовать в текущей базе данных.
G.4.7.2. Сценарии использования #
Этот раздел описывает, как создавать резервные копии планов и восстанавливать их в разных популярных сценариях.
G.4.7.2.1. Обновление версии сервера #
Выполните шаги ниже, чтобы сохранить планы при обновлении сервера со старой версии с несовместимым хранилищем данных.
Выполните резервное копирование планов до обновления.
CREATE TABLE storage_copy AS SELECT s.* FROM pgpro_multiplan_storage s JOIN pg_database d ON s.dbid = d.oid WHERE d.datname = 'db_name';
Обновите версию сервера.
Восстановите планы.
SELECT pgpro_multiplan_restore(query_string, NULL, hintstr, paramtypes, 'hintset', NULL, NULL) FROM storage_copy;
G.4.7.2.2. Миграция с sr_plan #
Чтобы мигрировать планы из устаревшего расширения sr_plan в pgpro_multiplan, выполните следующие шаги:
Выполните резервное копирование планов из хранилища расширения sr_plan.
CREATE TABLE storage_copy AS SELECT s.* FROM sr_plan_storage s JOIN pg_database d ON s.dbid = d.oid WHERE d.datname = 'db_name';
Восстановите планы в базу данных с расширением pgpro_multiplan.
SELECT pgpro_multiplan_restore(query_string, NULL, hintstr, paramtypes, 'hintset', NULL, NULL) FROM storage_copy;
G.4.7.2.3. Перенос планов между экземплярами серверов #
Чтобы перенести планы между двумя серверами, выполните следующее:
Подключитесь к исходному серверу.
Выполните резервное копирование планов в таблицу.
CREATE TABLE storage_copy AS SELECT s.* FROM pgpro_multiplan_storage s JOIN pg_database d ON s.dbid = d.oid WHERE d.datname = 'db_name';
Используйте утилиту pg_dump, чтобы выгрузить таблицу в файл.
$ pg_dump --table storage_copy -Ft postgres > storage_copy.tar
Подключитесь к целевому серверу и базе данных.
Переместите созданный файл выгрузки в целевую файловую систему.
Используйте утилиту pg_restore, чтобы восстановить таблицу с планами из файла выгрузки.
$ pg_restore --dbname postgres -Ft storage_copy.tar
Восстановите планы.
SELECT pgpro_multiplan_restore(query_string, sample_string, hintstr, paramtypes, plan_type, wildcards, NULL) FROM storage_copy; DROP TABLE storage_copy;
G.4.7.2.4. Перенос планов из "песочницы" в обычное хранилище #
Чтобы перенести планы из "песочницы" в обычное хранилище, выполните следующие шаги:
Установите для параметра pgpro_multiplan.sandbox значение
onи выполните резервное копирование планов из "песочницы".SET pgpro_multiplan.sandbox = ON; CREATE TABLE storage_copy AS SELECT s.* FROM pgpro_multiplan_storage s JOIN pg_database d ON s.dbid = d.oid WHERE d.datname = 'db_name';
Установите для параметра
pgpro_multiplan.sandboxзначениеoffи восстановите планы в обычное хранилище.SET pgpro_multiplan.sandbox = OFF; SELECT pgpro_multiplan_restore(query_string, sample_string, hintstr, paramtypes, plan_type, wildcards, NULL) FROM storage_copy;
G.4.7.2.5. Перенос планов между базами данных #
Чтобы перенести планы из одной базы данных в другую, подключитесь к целевой базе данных и восстановите планы, как показано ниже.
SELECT pgpro_multiplan_restore(s.query_string, s.sample_string, s.hintstr, s.paramtypes, s.plan_type, s.wildcards, NULL) FROM pgpro_multiplan_storage s JOIN pg_database d ON s.dbid = d.oid WHERE d.datname = 'db_name';
Здесь db_name — это имя базы данных, из которой вы хотите перенести планы.
G.4.7.2.6. Пример переноса планов #
Этот пример показывает, как перенести планы с одного экземпляра сервера на другой.
-- Подключитесь к исходному серверу
psql (17.4)
Type "help" for help.
-- В этом примере 1000 замороженных планов хранится в представлении pgpro_multiplan_storage
postgres=# select count(*) from pgpro_multiplan_storage;
count
-------
1000
(1 row)
-- Скопируйте планы из базы данных postgres в таблицу
postgres=# CREATE TABLE storage_copy AS SELECT s.*
FROM pgpro_multiplan_storage s
JOIN pg_database d ON s.dbid = d.oid
WHERE d.datname = 'postgres';
-- Выгрузите таблицу в файл архива
$ pg_dump --table storage_copy -Ft postgres > storage_copy.tar
-- Отключитесь от исходного сервера
-- Подключитесь к целевому серверу
./psql postgres
psql (16.8)
Type "help" for help.
-- Создайте расширение pgpro_multiplan и включите его
postgres=# create extension pgpro_multiplan;
CREATE EXTENSION
SET pgpro_multiplan.mode = 'frozen';
SET
-- Этот сервер не содержит планов
postgres=# select count(*) from pgpro_multiplan_storage;
count
-------
0
(1 row)
-- Переместите файл выгрузки с замороженными планами в целевую файловую систему
-- Восстановите таблицу с замороженными планами из файла выгрузки
$ pg_restore --dbname postgres -Ft storage_copy.tar
-- Восстановите замороженные планы из таблицы с помощью функции pgpro_multiplan_restore
postgres=# SELECT pgpro_multiplan_restore(query_string, sample_string, hintstr, paramtypes, 'serialized', NULL, NULL)
FROM storage_copy;
pgpro_multiplan_restore
----------------------------------
(8436876698844323073,871432885)
(8436876698844323073,573678316)
(8436876698844323073,1999378082)
(8436876698844323073,1681603536)
(8436876698844323073,3959620774)
...
(8436876698844323073,1263226437)
(8436876698844323073,4053700861)
(8436876698844323073,2418458596)
(8436876698844323073,413896030)
(1000 rows)
-- Функция восстановила 1000 замороженных планов. Результат показан в виде пар sql_hash и const_hash
-- Замороженные запросы были однотипными и отличались только константами, поэтому sql_hash одинаковый для всех планов
-- Удалите таблицу, используемую для восстановления планов
postgres=# DROP TABLE storage_copy;
DROP TABLE
-- Целевой сервер теперь тоже хранит 1000 замороженных планов
postgres=# select count(*) from pgpro_multiplan_storage;
count
-------
1000
(1 row)
-- Выключите pgpro_multiplan и выполните запрос
SET pgpro_multiplan.mode = '';
SET
postgres=# EXPLAIN (COSTS OFF) SELECT * FROM a WHERE x > 10;
QUERY PLAN
--------------------
Seq Scan on a
Filter: (x > 10)
(2 rows)
-- Включите pgpro_multiplan и выполните тот же запрос ещё раз
-- Теперь используется один из восстановленных планов
SET pgpro_multiplan.mode = 'frozen';
SET
postgres=# EXPLAIN (COSTS OFF) SELECT * FROM a WHERE x > 10;
QUERY PLAN
-------------------------------------
Custom Scan (MultiplanScan)
Plan is: frozen, serialized
SQL hash: 8436876698844323073
Const hash: 2295408638
Plan hash: 0
-> Index Scan using a_x_idx on a
Index Cond: (x > 10)
(7 rows)G.4.8. Совместимость с другими расширениями #
Для обеспечения совместимости pgpro_multiplan с другими расширениями необходимо в файле postgresql.conf в переменной shared_preload_libraries указать имена библиотек в определённом порядке:
pg_hint_plan: расширение pgpro_multiplan необходимо загрузить после pg_hint_plan.
shared_preload_libraries = 'pg_hint_plan, pgpro_multiplan'
aqo: расширение pgpro_multiplan необходимо загружать до aqo.
shared_preload_libraries = 'pgpro_multiplan, aqo'
pgpro_stats: расширение pgpro_multiplan необходимо загружать после pgpro_stats.
shared_preload_libraries = 'pgpro_stats, pgpro_multiplan'
G.4.9. Автоматическое приведение типов #
pgpro_multiplan пытается автоматически приводить типы констант из запроса к типам параметров запроса, для которого был заморожен план. Если привести типы невозможно, план игнорируется.
SELECT sql_hash, const_hash
FROM pgpro_multiplan_register_query('SELECT count(*) FROM a
WHERE x = $1', 'int');
-- Приведение типов возможно
EXPLAIN SELECT count(*) FROM a WHERE x = '1';
QUERY PLAN
-------------------------------------------------------------
Custom Scan (MultiplanScan) (cost=1.38..1.39 rows=1 width=8)
Plan is: tracked
SQL hash: -5166001356546372387
Const hash: 0
Plan hash: 0
-> Aggregate (cost=1.38..1.39 rows=1 width=8)
-> Seq Scan on a (cost=0.00..1.38 rows=1 width=0)
Filter: (x = $1)
-- Приведение типов возможно
EXPLAIN SELECT count(*) FROM a WHERE x = 1::bigint;
QUERY PLAN
-------------------------------------------------------------
Custom Scan (MultiplanScan) (cost=1.38..1.39 rows=1 width=8)
Plan is: tracked
SQL hash: -5166001356546372387
Const hash: 0
Plan hash: 0
-> Aggregate (cost=1.38..1.39 rows=1 width=8)
-> Seq Scan on a (cost=0.00..1.38 rows=1 width=0)
Filter: (x = $1)
-- Приведение типов невозможно
EXPLAIN SELECT count(*) FROM a WHERE x = 1111111111111;
QUERY PLAN
-------------------------------------------------------
Aggregate (cost=1.38..1.39 rows=1 width=8)
-> Seq Scan on a (cost=0.00..1.38 rows=1 width=0)
Filter: (x = '1111111111111'::bigint)G.4.10. Статистика использования планов #
Чтобы собирать статистику об использовании планов, укажите для параметра pgpro_multiplan.mode значение statistics. Доступ к этой статистике можно получить через представление pgpro_multiplan_stats. Параметр pgpro_multiplan.max_stats задаёт максимальное количество собираемых статистических значений. При достижении этого ограничения дальнейшая статистика игнорируется. Если план изменился, статистика использования этого плана сбрасывается и пересчитывается с новыми идентификаторами плана.
Для получения более детальной статистики планирования и выполнения запросов можно использовать расширение pgpro_stats (см. секцию Совместимость с другими расширениями). Доступ к этой статистике можно получить с помощью представления pgpro_stats_statements.
Вы можете объединить информацию из представлений pgpro_multiplan_stats и pgpro_stats_statements по полю planid.
Следующий пример демонстрирует, как собирать и просматривать статистику. В нём используется запрос и замороженный план из примера замороженного плана.
-- Включите сбор статистики
SET pgpro_multiplan.mode = 'frozen, statistics';
-- Выполните запрос
SELECT count(*) FROM a
WHERE x = 1 OR (x > 11 AND x < 22) OR x = 22;
count
-------
12
(1 row)
-- Теперь можно посмотреть статистику использования плана
SELECT * FROM pgpro_multiplan_stats;
dbid | sql_hash | const_hash | plan_hash | planid | counter
------+---------------------+------------+-----------+---------------------+---------
5 | 6062491547151210914 | 2413041345 | 0 | 3549961214127427294 | 1
(1 row)G.4.11. Интеграция с AQE #
Расширение pgpro_multiplan может работать совместно с адаптивным выполнением запросов (adaptive query execution, AQE), предоставляя более гибкие возможности для управления планами выполнения запросов.
AQE пытается переоптимизировать запрос, если во время выполнения запроса срабатывает определённый триггер, указывающий на неоптимальность плана. Чтобы включить AQE, используйте параметр конфигурации aqe_enable.
Параметр конфигурации pgpro_multiplan.aqe_mode задаёт функции, связанные с AQE, в виде списка, разделённого запятыми.
G.4.11.1. Управление планами в реальном времени #
При управлении планами в реальном времени pgpro_multiplan автоматически добавляет планы, созданные с помощью AQE, в список разрешённых планов.
Чтобы включить эту функциональность, выполните следующие шаги:
Установите для параметра aqe_enable значение
on, чтобы активировать AQE.Укажите один или несколько необходимых триггеров AQE с помощью параметров aqe_sql_execution_time_trigger, aqe_rows_underestimation_rate_trigger и aqe_backend_memory_used_trigger.
Укажите для параметра pgpro_multiplan.mode значение
baseline, чтобы включить использование разрешённых планов.Укажите для параметра pgpro_multiplan.aqe_mode значение
auto_approve_plans.
В следующем примере показано, как использовать управление планами в реальном времени.
INSERT INTO a SELECT x, x AS y FROM generate_series(1001,2000) x;
-- Включите AQE и триггер количества обработанных кортежей узлов
SET aqe_enable = 'on';
SET aqe_rows_underestimation_rate_trigger = 2;
-- Настройте режимы pgpro_multiplan
SET pgpro_multiplan.mode = 'baseline';
SET pgpro_multiplan.aqe_mode = 'auto_approve_plans';
-- Выполните запрос
SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 2000 AND t2.y > 900;
count
-------
1100
(1 row)
-- Запрос был переоптимизирован с помощь AQE в соответствии с триггером
-- План выполнения запроса был сохранён в список базовых (разрешённых) планов
-- Теперь можно увидеть этот план в соответствующем представлении
SELECT * FROM pgpro_multiplan_storage \gx
-[ RECORD 1 ]-+------------------------------------------------------------------------------------
dbid | 16384
sql_hash | 771426262442742808
const_hash | 0
plan_hash | -487722818968417375
valid | t
cost | 75.78750000000001
sample_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 2000 AND t2.y > 900;
query_string | SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= $1 AND t2.y > $2;
paramtypes |
query | <>
plan_type | baseline
plan | <>
hintstr | Leading(("t1" "t2" )) HashJoin("t1" "t2") IndexScan("t2" "a_y_idx") SeqScan("t1")
wildcards |
-- Выключите AQE
RESET aqe_enable;
RESET aqe_rows_underestimation_rate_trigger;
-- Выполните тот же запрос и посмотрите, что используется ранее сохранённый план
explain analyze
SELECT count(*) FROM a t1, a t2 WHERE t1.x = t2.x AND t1.y <= 2000 AND t2.y > 900;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Custom Scan (MultiplanScan) (cost=52.03..52.04 rows=1 width=8) (actual time=2.148..2.150 rows=1 loops=1)
Plan is: baseline
SQL hash: 771426262442742808
Const hash: 0
Plan hash: -487722818968417375
-> Aggregate (cost=52.03..52.04 rows=1 width=8) (actual time=2.148..2.149 rows=1 loops=1)
-> Hash Join (cost=13.78..51.65 rows=150 width=0) (actual time=1.390..2.051 rows=1100 loops=1)
Hash Cond: (t1.x = t2.x)
-> Seq Scan on a t1 (cost=0.00..30.75 rows=1500 width=4) (actual time=0.028..0.597 rows=2000 loops=1)
Filter: (y <= 2000)
-> Hash (cost=11.90..11.90 rows=150 width=4) (actual time=0.993..0.993 rows=1100 loops=1)
Buckets: 2048 (originally 1024) Batches: 1 (originally 1) Memory Usage: 55kB
-> Index Scan using a_y_idx on a t2 (cost=0.28..11.90 rows=150 width=4) (actual time=0.026..0.695 rows=1100 loops=1)
Index Cond: (y > 900)
Planning Time: 0.460 ms
Execution Time: 2.194 ms
(16 rows)G.4.11.2. Индивидуальные значения триггеров #
Расширение pgpro_multiplan разрешает переопределять и настраивать глобальные значения триггеров AQE> для отдельных запросов. Глобальные триггеры указываются в параметрах конфигурации aqe_sql_execution_time_trigger, aqe_rows_underestimation_rate_trigger и aqe_backend_memory_used_trigger.
Чтобы использовать эту функциональность, выполните следующие шаги:
Установите для параметра aqe_enable значение
on, чтобы активировать AQE.Укажите для параметра pgpro_multiplan.aqe_mode значение
individual_triggers.Вызовите функцию set_aqe_trigger для каждого запроса, триггеры которого нужно переопределить.
Все индивидуальные значения триггеров показаны в представлении aqe_triggers. Параметр pgpro_multiplan.aqe_max_items указывает максимальное количество хранимых значений триггеров.
G.4.11.3. Статистика AQE #
pgpro_multiplan может собирать статистику AQE для всех выражений, которые рассматриваются для переоптимизации. Эта статистика хранится в разделяемой памяти до выключения сервера и не реплицируется.
Выполните следующие шаги для включения сбора статистики:
Установите для параметра aqe_enable значение
on, чтобы активировать AQE.Укажите для параметра pgpro_multiplan.aqe_mode значение
statistics.Включите вычисление идентификаторов запросов с помощью параметра compute_query_id.
Все статистические значения показаны в представлении aqe_stats. Параметр pgpro_multiplan.aqe_max_stats указывает максимальное количество хранимых статистических значений. Дальнейшие статистические значения игнорируются.
G.4.12. Представления #
G.4.12.1. Представление pgpro_multiplan_storage #
Представление pgpro_multiplan_storage содержит подробную информацию обо всех планах. Столбцы представления показаны в Таблице G.4.
Таблица G.4. Столбцы pgpro_multiplan_storage
| Имя | Тип | Описание |
|---|---|---|
dbid | oid | Идентификатор базы данных, в которой выполняется запрос |
sql_hash | bigint | Внутренний идентификатор запроса |
const_hash | bigint | Хеш непараметризованных констант для замороженных планов, 0 для планов с шаблонами и разрешённых планов |
plan_hash | bigint | Внутренний идентификатор разрешённого плана, 0 для замороженных планов и планов с шаблонами |
valid | boolean | FALSE, если план был аннулирован при последнем использовании |
cost | float | Стоимость разрешённого плана, 0 для замороженных планов и планов с шаблонами |
sample_string | text | Непараметризованный запрос с константами |
query_string | text | Параметризованный запрос |
paramtypes | regtype[] | Массив с типами параметров, использованными в запросе |
query | text | Внутреннее представление запроса |
plan | text | Внутреннее представление плана |
plan_type | text | Тип плана. Для замороженных планов: serialized или hintset. Для планов с шаблонами: template. Для разрешённых планов: baseline |
hintstr | text | Набор указаний, сформированный на основе плана |
wildcards | text | Регулярное выражение, используемое для плана с шаблонами (template), NULL для замороженных и разрешённых планов |
G.4.12.2. Представление pgpro_multiplan_local_cache #
Представление pgpro_multiplan_local_cache содержит подробную информацию о замороженных планах в локальном кеше. Замороженный план добавляется в локальный кеш, если он был использован хотя бы один раз. Размер локального кеша ограничивается параметром pgpro_multiplan.max_local_cache_size. Столбцы представления показаны в Таблице G.5.
Таблица G.5. Столбцы pgpro_multiplan_local_cache
| Имя | Тип | Описание |
|---|---|---|
sql_hash | bigint | Внутренний идентификатор запроса |
const_hash | bigint | Хеш непараметризованных констант |
fs_is_frozen | boolean | TRUE, если запрос заморожен |
fs_is_valid | boolean | TRUE, если замороженный оператор действителен |
ps_is_valid | boolean | TRUE, если соответствующий подготовленный оператор действителен |
query_string | text | Текст запроса |
query | text | Внутреннее представление запроса |
paramtypes | regtype[] | Массив с типами параметров, использованными в запросе |
hintstr | text | Набор указаний, сформированный на основе плана |
G.4.12.3. Представление pgpro_multiplan_captured_queries #
Представление pgpro_multiplan_captured_queries содержит подробную информацию обо всех запросах, отслеживаемых в сеансах. Столбцы представления показаны в Таблице G.6.
Таблица G.6. Столбцы pgpro_multiplan_captured_queries
| Имя | Тип | Описание |
|---|---|---|
dbid | oid | Идентификатор базы данных, в которой выполняется запрос |
sql_hash | bigint | Внутренний идентификатор запроса |
queryid | bigint | Стандартный идентификатор запроса |
plan_hash | bigint | Внутренний идентификатор плана |
planid | bigint | Идентификатор плана, совместимый с расширением pgpro_stats |
cost | float | Стоимость плана |
sample_string | text | Последний использованный непараметризованный запрос с константами |
query_string | text | Последний использованный параметризованный запрос |
hintstr | text | Набор указаний, сформированный на основе плана |
explain_plan | text | План, показанный командой EXPLAIN |
G.4.12.4. Представление pgpro_multiplan_stats #
Представление pgpro_multiplan_stats предоставляет статистику использования планов. Столбцы представления показаны в Таблице G.7.
Таблица G.7. Столбцы pgpro_multiplan_stats
| Имя | Тип | Описание |
|---|---|---|
dbid | oid | Идентификатор базы данных, в которой выполняется запрос |
sql_hash | bigint | Внутренний идентификатор запроса |
plan_hash | bigint | Внутренний идентификатор плана |
planid | bigint | Идентификатор плана, совместимый с расширением pgpro_stats |
counter | bigint | Количество использований плана |
G.4.12.5. Представление aqe_triggers #
Представление aqe_triggers содержит информацию об индивидуальных значениях триггеров AQE. Столбцы представления показаны в Таблице G.8.
Таблица G.8. Столбцы aqe_triggers
| Имя | Тип | Описание |
|---|---|---|
dbid | oid | Идентификатор базы данных, в которой выполняется запрос |
sql_hash | bigint | Внутренний идентификатор запроса |
query_string | text | Параметризованный запрос |
execution_time | int | Значение для триггера времени выполнения запроса, в миллисекундах. NULL, если используется глобальное значение триггера |
memory | int | Значение для триггера потребления памяти рабочим процессом. NULL, если используется глобальное значение триггера |
underestimation_rate | double | Коэффициент для триггера количества обработанных кортежей узлов. NULL, если используется глобальное значение триггера |
G.4.12.6. Представление aqe_stats #
Представление aqe_stats содержит сводную статистику о переоптимизациях AQE. Это представление содержит одну строку для каждой комбинации идентификатора базы данных, запроса и плана выполнения. Столбцы представления показаны в Таблице G.9.
Таблица G.9. Столбцы aqe_stats
| Имя | Тип | Описание |
|---|---|---|
dbid | oid | Идентификатор базы данных, в которой выполняется запрос |
sql_hash | bigint | Внутренний идентификатор запроса |
planid | bigint | Идентификатор плана выполнения запроса |
query | text | Внутреннее представление запроса |
last_updated | timestamp with time zone | Время последнего обновления статистики |
exec_num | bigint | Количество выполнений запроса |
min_attempts | integer | Минимальное количество переоптимизаций запроса |
max_attempts | integer | Максимальное количество переоптимизаций запроса |
total_attempts | integer | Общее количество переоптимизаций запроса |
reason_repeated_plan | bigint | Количество отключений AQE из-за генерации повторного плана выполнения |
reason_no_data | bigint | Количество отключений AQE из-за отсутствия новой информации, полученной во время выполнения |
reason_max_reruns | bigint | Количество отключений AQE из-за достижения максимального количества перезапусков |
reason_external | bigint | Количество раз, когда AQE было отключено расширением, например, pgpro_multiplan |
reruns_forced | bigint | Общее количество переоптимизаций, вызванных ручным триггером |
reruns_time | bigint | Общее количество переоптимизаций, вызванных триггером времени выполнения запроса |
reruns_underestimation | bigint | Общее количество переоптимизаций, вызванных триггером количества обработанных кортежей узлов |
reruns_memory | bigint | Общее количество переоптимизаций, вызванных триггером потребления памяти рабочим процессом |
min_planning_time | double precision | Минимальное время, затраченное на планирование, в миллисекундах |
max_planning_time | double precision | Максимальное время, затраченное на планирование, в миллисекундах |
mean_planning_time | double precision | Среднее время, затраченное на планирование, в миллисекундах |
stddev_planning_time | double precision | Стандартное отклонение времени, затраченного на планирование, в миллисекундах |
min_exec_time | double precision | Минимальное время, затраченное на выполнение запроса, в миллисекундах |
max_exec_time | double precision | Максимальное время, затраченное на выполнение запроса, в миллисекундах |
mean_exec_time | double precision | Среднее время, затраченное на выполнение запроса, в миллисекундах |
stddev_exec_time | double precision | Стандартное отклонение времени, затраченного на выполнение запроса, в миллисекундах |
G.4.13. Функции #
Вызывать нижеуказанные функции могут только суперпользователи.
-
pgpro_multiplan_register_query(query_stringtext) returns record
pgpro_multiplan_register_query(#query_stringtext,VARIADICregtype[]) returns record Регистрирует запрос, указанный аргументом
query_string. Возвращает уникальную паруsql_hashиconst_hash.-
pgpro_multiplan_unregister_query() returns bool# Удаляет зарегистрированный запрос. Если нет ошибок, возвращает
true.-
pgpro_multiplan_freeze(#plan_typetext) returns bool Фиксирует последний использованный для запроса план и сохраняет его в постоянном хранилище pgpro_multiplan, к которому можно получить доступ в представлении pgpro_multiplan_storage. Допустимые значения необязательного аргумента
plan_type:serialized(по умолчанию),hintset,templateиbaseline. Если план был успешно зафиксирован, возвращаетtrue. За подробной информацией о типах планов обратитесь к разделу Поддерживаемые режимы и типы планов. За подробной информацией об этой функции и примерами использования обратитесь к разделу Заморозка планов.-
pgpro_multiplan_unfreeze(#sql_hashbigint,const_hashbigint) returns bool Удаляет указанный план из постоянного хранилища, но оставляет запрос зарегистрированным. Если нет ошибок, возвращает
true.-
pgpro_multiplan_remove(#dbidoid,sql_hashbigint,const_hashbigint) returns bool Удаляет замороженный план, который идентифицируется по
sql_hashиconst_hash, из базы данных, определяемой аргументомdbid. Опуститеdbid, чтобы удалить план из текущей базы данных. Эта функция работает, как функции pgpro_multiplan_unfreeze и pgpro_multiplan_unregister_query, вызываемые последовательно. Если план был успешно удалён, возвращаетtrue.-
pgpro_multiplan_reset(#dbidoid) returns bigint Удаляет все записи в представлении
pgpro_multiplan_storageдля указанной базы данных. Чтобы удалить данные, собранные pgpro_multiplan для текущей базы данных, не указывайтеdbid. Чтобы сбросить данные для всех баз данных, установите для параметраdbidзначение NULL. Возвращает количество удалённых записей.-
pgpro_multiplan_reload_frozen_plancache() returns bool# Удаляет все замороженные планы и снова загружает их в представление
pgpro_multiplan_storage. Также удаляет операторы, которые были зарегистрированы, но не заморожены. Если нет ошибок, возвращаетtrue.-
pgpro_multiplan_stats() returns table# Возвращает статистику использования планов из представления pgpro_multiplan_stats.
-
pgpro_multiplan_registered_query(#sql_hashbigint,const_hashbigint) returns table Возвращает зарегистрированный запрос с указанными параметрами
sql_hashиconst_hash, даже если он не заморожен, только для целей отладки. Работает, если запрос зарегистрирован в текущем обслуживающем процессе или заморожен в текущей базе данных.-
pgpro_multiplan_captured_approve(#dbidoid,sql_hashbigint,plan_hashbigint) returns bool Добавляет указанный план для захваченного запроса в набор базовых (разрешённых) планов и сохраняет его в представлении
pgpro_multiplan_storage. Если план был успешно добавлен, возвращаетtrue.-
pgpro_multiplan_remove_baseline(#dbidoid,sql_hashbigint,plan_hashbigint) returns bool Удаляет разрешённый план, который идентифицируется по
sql_hashиplan_hash, из базы данных, определяемой аргументомdbid. Опуститеdbid, чтобы удалить разрешённый план из текущей базы данных. Если план был успешно удалён, возвращаетtrue.-
pgpro_multiplan_remove_template(#dbidoid,sql_hashbigint,table_hashbigint) returns bool Удаляет план с шаблонами, который идентифицируется по
sql_hashиtable_hash, из базы данных, определяемой аргументомdbid. Опуститеdbid, чтобы удалить план из текущей базы данных. Если план был успешно удалён, возвращаетtrue.-
pgpro_multiplan_enable(#dbidoid,sql_hashbigint,const_hashbigint,enablebool) returns bool Включает или отключает замороженный план, который идентифицируется по
sql_hashиconst_hash. Аргументdbidопределяет идентификатор целевой базы данных. Опуститеdbid, чтобы использовать эту функцию для плана в текущей базе данных. Для последнего аргумента укажитеtrue, чтобы включить план, илиfalse, чтобы отключить его. Если состояние плана было успешно изменено, возвращаетtrue.-
pgpro_multiplan_enable_baseline(#dbidoid,sql_hashbigint,plan_hashbigint,enablebool) returns bool Включает или отключает разрешённый план, который идентифицируется по
sql_hashиplan_hash. Аргументdbidопределяет идентификатор целевой базы данных. Опуститеdbid, чтобы использовать эту функцию для плана в текущей базе данных. Для последнего аргумента укажитеtrue, чтобы включить план, илиfalse, чтобы отключить его. Если состояние плана было успешно изменено, возвращаетtrue.-
pgpro_multiplan_enable_template(#dbidoid,sql_hashbigint,table_hashbigint,enablebool) returns bool Включает или отключает план с шаблонами, который идентифицируется по
sql_hashиtable_hash. Аргументdbidопределяет идентификатор целевой базы данных. Опуститеdbid, чтобы использовать эту функцию для плана в текущей базе данных. Для последнего аргумента укажитеtrue, чтобы включить план, илиfalse, чтобы отключить его. Если состояние плана было успешно изменено, возвращаетtrue.-
pgpro_multiplan_set_plan_type(#sql_hashbigint,const_hashbigint,plan_typetext) returns bool Устанавливает тип плана запроса для замороженного оператора. Допустимые значения аргумента
plan_type:serializedиhintset. Чтобы иметь возможность использовать планы на основе указаний, необходимо загрузить расширение pg_hint_plan. Если тип плана был успешно изменён, возвращаетtrue.-
pgpro_multiplan_update_hintset(#dbidoid,sql_hashbigint,const_hashbigint,hintsettext) returns bool Заменяет сгенерированный набор указаний для замороженного плана типа
hintsetна указанный набор пользовательских указаний. План идентифицируется поsql_hashиconst_hash. Аргументdbidопределяет идентификатор целевой базы данных. Опуститеdbid, чтобы использовать эту функцию для плана в текущей базе данных. Аргументhintsetзадаёт строку с пользовательскими указаниями. Эта строка не должна задаваться в комментарии особого вида, используемого в pg_hint_plan, то есть она не должна начинаться с символов/*+и заканчиваться символами*/. Если набор указаний был успешно изменён, возвращаетtrue.-
pgpro_multiplan_update_template_hintset(#dbidoid,sql_hashbigint,table_hashbigint,hintsettext) returns bool Заменяет сгенерированный набор указаний для плана с шаблонами на указанный набор пользовательских указаний. План идентифицируется по
sql_hashиtable_hash. Аргументdbidопределяет идентификатор целевой базы данных. Опуститеdbid, чтобы использовать эту функцию для плана в текущей базе данных. Аргументhintsetзадаёт строку с пользовательскими указаниями. Эта строка не должна задаваться в комментарии особого вида, используемого в pg_hint_plan, то есть она не должна начинаться с символов/*+и заканчиваться символами*/. Если набор указаний был успешно изменён, возвращаетtrue.-
pgpro_multiplan_update_baseline_cost(#sql_hashbigint,plan_hashbigint) returns bool Обновляет стоимость указанного разрешённого плана в постоянном хранилище pgpro_multiplan. Если стоимость была успешно обновлена, возвращает
true.-
pgpro_multiplan_captured_clean() returns bigint# Удаляет все записи из представления pgpro_multiplan_captured_queries. Возвращает количество удалённых записей.
-
get_sql_hash(#query_stringtext) returns bigint Возвращает внутренний идентификатор (
sql_hash) для указанного запроса.-
set_aqe_trigger(trigger_nametext,trigger_valint,query_stringtext) returns bool
set_aqe_trigger(#trigger_nametext,trigger_valdouble precision,query_stringtext) returns bool Задаёт или сбрасывает индивидуальное значение триггера AQE для указанного запроса. Индивидуальное значение триггера переопределяет глобальное значение триггера, указанное в параметре конфигурации AQE. Чтобы эта функциональность работала, значение
individual_triggersдолжно быть указано в параметре pgpro_multiplan.aqe_mode.Эта функция имеет следующие аргументы:
trigger_name: имя триггера. Разрешены следующие значения:execution_time: триггер времени выполнения запроса. Соответствует параметру конфигурации aqe_sql_execution_time_trigger.memory: триггер потребления памяти рабочим процессом. Соответствует параметру конфигурации aqe_backend_memory_used_trigger.underestimation_rate: триггер количества обработанных кортежей узлов. Соответствует параметру конфигурации aqe_rows_underestimation_rate_trigger.
trigger_val: значение триггера. Для триггеровexecution_timeиmemoryуказывайте целочисленные значения. Дляunderestimation_rateможно указать значения с двойной точностью. Чтобы сбросить индивидуальное значение триггера, передайте в качестве значенияNULLили отрицательное число меньше -1.query_string: текст запроса.
Если нет ошибок, эта функция возвращает
true.-
aqe_triggers_reset(#dbidoid) returns bigint Удаляет все записи из представления
aqe_triggersдля указанной базы данных. Чтобы очистить представлениеaqe_triggersдля текущей базы данных, не указывайтеdbid. Чтобы удалить записи из представления для всех баз данных, установите для параметраdbidзначениеNULL. Возвращает количество удалённых записей.-
aqe_stats_reset(#dbidoid) returns bigint Удаляет все записи из представления
aqe_statsдля указанной базы данных. Чтобы очистить представлениеaqe_statsдля текущей базы данных, не указывайтеdbid. Чтобы удалить записи из представления для всех баз данных, установите для параметраdbidзначениеNULL. Возвращает количество удалённых записей.-
pgpro_multiplan_restore(#query_stringtext,sample_stringtext,hintstrtext,paramtypesregtype[],plan_typetext,wildcardstext,statusint) returns record Восстанавливает план для указанного запроса в текущую базу данных.
Эта функция имеет следующие аргументы:
query_string: запрос с параметрами$(аналогичноnPREPARE), для которого восстанавливается план на основе набора указаний.statement_nameASsample_string: непараметризованный запрос с константами.hintstr: набор указаний, которые описывают нужный план. Эти указания должны поддерживаться расширением pg_hint_plan. Для планов с типамиbaselineиtemplateэтот аргумент не может представлять собой пустую строку. Для остальных типов планов, если для этого аргумента указано значениеNULLили пустая строка, будет использоваться стандартный план.parameter_type: массив с типами параметров, используемых в запросе. Если для аргумента указано значениеNULL, типы параметров должны быть определены автоматически.plan_type: тип плана. Допустимые значения:serialized,hintset,baselineиtemplate. За дополнительной информацией о типах планов обратитесь к разделу Поддерживаемые режимы и типы планов.wildcards: регулярное выражение POSIX, используемое только для планов с типомtemplate, чтобы проверять соответствия имён таблиц. Для остальных типов планов этот аргумент игнорируется, и можно для него указывать значениеNULL.status: этот аргумент зарезервирован для использования в будущем. На текущий момент всегда устанавливайте для него значениеNULLили0.
Функция возвращает уникальную пару
sql_hashиconst_hash, если план был успешно восстановлен. В противном случае, она возвращаетNULL.За подробной информацией об этой функции и сценариях использования обратитесь к разделу Резервное копирование и восстановление планов.
G.4.14. Параметры конфигурации #
pgpro_multiplan.mode(string) #Список включённых режимов pgpro_multiplan, разделённых запятой. Доступны следующие значения:
frozen: разрешает использование замороженных планов (и сериализованных, и с наборами указаний).wildcards: разрешает использование планов с шаблонами.baseline: разрешает использование базовых (разрешённых) планов.statistics: разрешает сбор статистики использования планов. Эта статистика хранится в представлении pgpro_multiplan_stats. Это значение параметра может быть указано только совместно с одним или несколькими типами планов.
SET pgpro_multiplan.mode = 'frozen, wildcards, baseline, statistics';
Подробнее о типах планов можно узнать в разделе Поддерживаемые режимы и типы планов. За информацией о сборе статистики обратитесь к разделу Статистика.
По умолчанию для параметра
pgpro_multiplan.modeзадана пустая строка, означающая, что все режимы планов выключены. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.aqe_mode(string) #Включённые функции, связанные с AQE, в виде списка, разделённого запятыми. Доступны следующие значения:
auto_approve_plans: включает управление планами в реальном времени.individual_triggers: разрешает указывать индивидуальные значения триггеров AQE.statistics: включает сбор статистики AQE.
SET pgpro_multiplan.aqe_mode = 'auto_approve_plans, individual_triggers, statistics';
Чтобы эта функциональность работала, AQE должно быть включено с помощью параметра конфигурации aqe_enable.
По умолчанию для параметра
pgpro_multiplan.aqe_modeуказана пустая строка. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.max_stats(integer) #Задаёт максимальное количество статистических значений, которые могут храниться в представлении
pgpro_multiplan_stats. Дальнейшая статистика будет игнорироваться. Значение по умолчанию — 5000. Этот параметр можно задать только при запуске сервера.pgpro_multiplan.max_items(integer) #Задаёт максимальное количество записей, с которым может работать pgpro_multiplan. Значение по умолчанию — 100. Этот параметр можно задать только при запуске сервера.
pgpro_multiplan.auto_tracking(boolean) #Позволяет pgpro_multiplan автоматически регистрировать запросы, выполняемые с помощью команд
EXPLAINиEXPLAIN EXECUTE. Значение по умолчанию —off. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.max_local_cache_size(integer) #Задаёт максимальный размер локального кеша, в килобайтах. Значение по умолчанию —
0, что означает отсутствие ограничения. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.wal_rw(boolean) #Включает физическую репликацию данных pgpro_multiplan. При значении
offна главном сервере данные на резервный сервер не передаются. При значенииoffна резервном сервере любые данные, передаваемые с главного сервера, игнорируются. Значение по умолчанию —off. Этот параметр можно задать только при запуске сервера.pgpro_multiplan.auto_capturing(boolean) #Включает автоматическое отслеживание запросов в pgpro_multiplan. Если для этого параметра конфигурации установить значение
on, в представлении pgpro_multiplan_captured_queries можно будет увидеть запросы с константами в текстовой форме и параметризованные запросы. Также будут видны все планы для каждого запроса. Информация о выполненных запросах хранится до перезапуска сервера. Значение по умолчанию —off. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.max_captured_items(integer) #Задаёт максимальное количество запросов, которые может отслеживать pgpro_multiplan. Значение по умолчанию — 1000. Этот параметр можно задать только при запуске сервера.
pgpro_multiplan.sandbox(boolean) #Включает резервирование отдельных зон разделяемой памяти для ведущего и резервного узла, что позволяет тестировать и анализировать запросы с существующим набором данных без влияния на работу узла. Если на резервном узле установлено значение
on, pgpro_multiplan замораживает планы выполнения запросов только на этом узле и хранит их в альтернативном хранилище планов — «песочнице». Если параметр включён на ведущем узле, расширение использует отдельную зону разделяемой памяти, данные которой не реплицируются на резервные узлы. При изменении значения параметра сбрасывается кеш pgpro_multiplan. Значение по умолчанию —off. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.wildcards(string) #Регулярное выражение POSIX, которое используется для планов с шаблонами для проверки соответствия имён таблиц, задействованных в запросах. Чтобы разрешить использование планов с шаблонами, укажите для параметра pgpro_multiplan.mode значение
wildcards. Значениеpgpro_multiplan.wildcardsзамораживается вместе с соответствующим запросом. Значение по умолчанию —.*, которое означает соответствие любому имени таблицы.pgpro_multiplan.show_explain_details(boolean) #Разрешает отображение идентификаторов планов в выводе команды
EXPLAIN. Значение по умолчанию —on. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.show_hint_string(boolean) #Разрешает отображение наборов указаний, сформированных на основе планов, в выводе команды
EXPLAIN. Значение по умолчанию —off. Изменить этот параметр могут только суперпользователи.pgpro_multiplan.aqe_max_items(integer) #Задаёт максимальное количество хранимых индивидуальных значений триггеров AQE. Значение по умолчанию —
100. Этот параметр можно задать только при запуске сервера.pgpro_multiplan.aqe_max_stats(integer) #Задаёт максимальное количество собираемых статистических значений AQE. Дальнейшие статистические значения игнорируются. Значение по умолчанию —
5000. Этот параметр можно задать только при запуске сервера.