auto_dump. Сбор и воспроизведение проблемных запросов
В исходном дистрибутиве установлено по умолчанию: нет.
Связанные компоненты: отсутствуют.
Схема размещения: не используется.
Данное расширение реализует процесс получения воспроизведения медленного выполнения запроса без использования платформы 1С:Предприятие. Расширение:
- Формирует выгрузку таблиц, которые используются в запросе. Можно включать в выгрузку, как временные таблицы, так и постоянные таблицы;
- Создает SQL-запрос для переноса и подготовки данных для воспроизведения проблемного запроса;
- Создает файл проблемного SQL-запроса для его воспроизведения и получает его план выполнения (с помощью команды
EXPLAIN).
Доработка
Доработка не проводилась.
Установка
Для начала использования расширения выполните следующие действия:
-
Пропишите в конфигурационном файле (
postgresql.conf/postgres.yml) СУБД Pangolin название расширения в настроечный параметрshared_preload_libraries:shared_preload_libraries = 'auto_dump' -
Включите расширение путем заполнения основного конфигурационного параметра:
auto_dump.enable = on -
Настройте расширение, для этого выполните конфигурирование дополнительных параметров.
-
Выполните перезапуск сервера:
systemctl restart postgresql -
Далее расширение нужно установить в целевую БД командой:
CREATE EXTENSION auto_dump;
Настройка
Конфигурационные параметры
Основные параметры
Параметр | Тип данных | Значение по умолчанию | Описание |
|---|---|---|---|
|
|
| Признак включения расширения |
|
| – | Путь директории, в которую будут сохраняться файлы с дампами таблиц. Параметр обязателен для настройки. У пользователя, под которым запущена служба СУБД, должны быть права на доступ к этой директории |
Параметры, определяющие объем данных в дампе
Параметр | Тип данных | Значение по умолчанию | Описание |
|---|---|---|---|
|
|
| При включении параметра в дамп будут добавлены временные таблицы сессии, участвующие в текущем запросе |
|
|
| При включении параметра в дамп будут добавлены все постоянные таблицы, участвующие в текущем запросе |
|
|
| При включении параметра в дамп будут добавлены все временные таблицы сессии, в том числе и участвующие в текущем запросе |
|
|
| При включении параметра в дамп будет записано содержимое таблиц, для которых снимается дамп. Если параметр выключен, то в SQL-запросе будет описано только создание таблиц, без их заполнения |
|
|
| При включении параметра в дамп будет записано создание индексов для таблиц, которые участвуют в дампе |
|
|
| Определяет метод выгрузки данных таблиц Если параметр включен, данные таблиц выгружаются с помощью команды |
|
|
| При включении параметра будет сформирован файл с SQL-запросом, для которого сформирован дамп |
|
|
| При включении параметра будет сформирован файл с SQL-командами создания таблиц, для которых снимается дамп |
|
|
| При включении параметра будет сформирован файл с планом выполнения текущего SQL-запроса |
Параметры, включающие критерии срабатывания
Параметр | Тип данных | Значение по умолчанию | Описание |
|---|---|---|---|
|
| – | Фрагмент SQL-запроса, при появлении которого в запросе будет осуществлено срабатывание получения дампа |
|
|
| При включении параметра будет осуществляться дамп запросов отмененных со стороны СУБД (например, командой |
|
|
| При включении параметра будет анализироваться ожидаемое и фактическое количество строк для всех запросов. Чтобы сработало автоматическое формирование дампа по запросу, должны одновременно выполниться два критерия |
|
|
| Критерий срабатывания автоматического дампа по абсолютной разнице между ожидаемым и фактическим количеством строк. Анализируются все узлы плана. Если ожидаемое количество строк отличается от фактического количества строк более чем на заданное в параметре число, то критерий считается выполнен. Если значение равно |
|
|
| Критерий срабатывания автоматического дампа по разнице в процентах между ожидаемым и фактическим количеством строк В качестве параметра устанавливается число от 0 до 100. Анализируются все узлы плана. По каждому узлу проверяется отношение суммы ожидаемого количества строк и фактического количества строк к ожидаемому количеству строк. Если это отношение превышает установленный параметр, то критерий считается выполненным. Если значение равно |
|
|
| Сохранить выгрузку запроса, если время его выполнения превышает значение |
|
|
| Задает значение тайм-аута для |
Ограничения
Не рекомендуется настраивать auto_dump таким образом, чтобы оно выгружало каждый запрос. Расширение предназначено для отладки и не может использоваться для непрерывного мониторинга.
Ограничения:
- Расширение
auto_dumpнесовместимо с командойPREPARE TRANSACTIONпри работе с временными таблицами. - Если включен параметр
auto_dump.dump_all_temp_tables, расширениеauto_dumpне может обратиться к временным пространствам имен из автономных транзакций.
Использование модуля
Пример использования
-
С помощью технологического журнала был получен текст SQL-запроса:
SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef) -
В конфигурационном файле
postgresql.conf/postgres.ymlбыли добавлены строки:shared_preload_libraries = ‘auto_dump’
auto_dump.enable = on
auto_dump.output_directory = ‘/tmp/auto_d’
auto_dump.dump_on_query_string = ‘LEFT OUTER JOIN _Reference7X1’ -
Перезапуск службы СУБД:
user@server: sudo systemctl restart postgresql@16-main.service -
Добавление расширения в базу данных
auto_d:user@server: psql -h localhost -U postgres -d auto_dauto_d=# create extension auto_dump;
CREATE EXTENSION -
Пользователь в 1С выполнил действие, которое использует проблемный запрос. После этого в каталоге
/tmp/auto_dпоявился новый каталог, который имеет следующий форматPIDПроцесса-ГГГГ-ММ-ДД-ЧЧ-ММ-СС-ПорядковыйНомер.user@server:/tmp/auto_d/71491-2025_06_11_12_42_36_00$ ls -l
-rw------- 1 postgres postgres 3241 июн 11 12:42 create.sql
-rw------- 1 postgres postgres 6743 июн 11 12:42 createwithdata.sqlФайл
create.sqlсодержит текст:CREATE TEMPORARY TABLE tt3 (
_q_001_f_000rref bytea,
_q_001_f_001rref bytea,
_q_001_f_002 numeric(22,2)
);
CREATE INDEX tmpind_1 ON pg_temp.tt3 USING btree (_q_001_f_000rref);
ANALYZE tt3;
CREATE TEMPORARY TABLE tt2 (
_q_001_f_000rref bytea,
_q_001_f_001 numeric(16,2)
);
CREATE INDEX tmpind_0 ON pg_temp.tt2 USING btree (_q_001_f_000rref);
ANALYZE tt2;
/*
SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef);
*/
/*
Query Text: SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef)
Hash Join (cost=8.01..9.51 rows=22 width=79)
Hash Cond: (t1._q_001_f_000rref = t3._q_001_f_000rref)
-> Hash Left Join (cost=6.76..8.01 rows=22 width=72)
Hash Cond: (t1._q_001_f_001rref = t2._idrref)
-> Seq Scan on tt3 t1 (cost=0.00..1.22 rows=22 width=40)
-> Hash (cost=6.36..6.36 rows=36 width=64)
-> Seq Scan on _reference7x1 t2 (cost=0.00..6.36 rows=36 width=64)
-> Hash (cost=1.12..1.12 rows=12 width=24)
-> Seq Scan on tt2 t3 (cost=0.00..1.12 rows=12 width=24)
*/
/*
Query Text: SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef)
Hash Join (cost=8.01..9.51 rows=22 width=79) (actual time=0.027..0.037 rows=22 loops=1)
Output: t3._q_001_f_000rref, t3._q_001_f_001, t1._q_001_f_002, t1._q_001_f_001rref, t2._fld23
Hash Cond: (t1._q_001_f_000rref = t3._q_001_f_000rref)
Buffers: shared hit=6, local hit=2
-> Hash Left Join (cost=6.76..8.01 rows=22 width=72) (actual time=0.020..0.025 rows=22 loops=1)
Output: t1._q_001_f_002, t1._q_001_f_001rref, t1._q_001_f_000rref, t2._fld23
Inner Unique: true
Hash Cond: (t1._q_001_f_001rref = t2._idrref)
Buffers: shared hit=6, local hit=1
-> Seq Scan on pg_temp.tt3 t1 (cost=0.00..1.22 rows=22 width=40) (actual time=0.001..0.002 rows=22 loops=1)
Output: t1._q_001_f_000rref, t1._q_001_f_001rref, t1._q_001_f_002
Buffers: local hit=1
-> Hash (cost=6.36..6.36 rows=36 width=64) (actual time=0.016..0.016 rows=36 loops=1)
Output: t2._fld23, t2._idrref
Buckets: 1024 Batches: 1 Memory Usage: 11kB
Buffers: shared hit=6
-> Seq Scan on public._reference7x1 t2 (cost=0.00..6.36 rows=36 width=64) (actual time=0.003..0.011 rows=36 loops=1)
Output: t2._fld23, t2._idrref
Buffers: shared hit=6
-> Hash (cost=1.12..1.12 rows=12 width=24) (actual time=0.005..0.005 rows=12 loops=1)
Output: t3._q_001_f_000rref, t3._q_001_f_001
Buckets: 1024 Batches: 1 Memory Usage: 9kB
Buffers: local hit=1
-> Seq Scan on pg_temp.tt2 t3 (cost=0.00..1.12 rows=12 width=24) (actual time=0.002..0.002 rows=12 loops=1)
Output: t3._q_001_f_000rref, t3._q_001_f_001
Buffers: local hit=1
Settings: enable_mergejoin = 'off', cpu_operator_cost = '0.001'
*/Файл
createwithdata.sqlсодержит текст:CREATE TEMPORARY TABLE tt3 (
_q_001_f_000rref bytea,
_q_001_f_001rref bytea,
_q_001_f_002 numeric(22,2)
);
CREATE INDEX tmpind_1 ON pg_temp.tt3 USING btree (_q_001_f_000rref);
INSERT INTO tt3 (_q_001_f_000rref, _q_001_f_001rref, _q_001_f_002) VALUES
(E'\\x8ca0000d8843cd1b11dc8d043d710079',E'\\x8ca1000d8843cd1b11dc8ea92d97a749',36960.00),
(E'\\x8ca1000d8843cd1b11dc8ea92d97a74a',E'\\x8ca1000d8843cd1b11dc8ea92d97a749',123750.00);
ANALYZE tt3;
CREATE TEMPORARY TABLE tt2 (
_q_001_f_000rref bytea,
_q_001_f_001 numeric(16,2)
);
CREATE INDEX tmpind_0 ON pg_temp.tt2 USING btree (_q_001_f_000rref);
INSERT INTO tt2 (_q_001_f_000rref, _q_001_f_001) VALUES
(E'\\x8ca0000d8843cd1b11dc8d043d71007d',59500.00),
(E'\\x8ca0000d8843cd1b11dc8d043d710076',153176.73);
ANALYZE tt2;
/*
SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef);
*/
/*
Query Text: SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef)
Hash Join (cost=8.01..9.51 rows=22 width=79)
Hash Cond: (t1._q_001_f_000rref = t3._q_001_f_000rref)
-> Hash Left Join (cost=6.76..8.01 rows=22 width=72)
Hash Cond: (t1._q_001_f_001rref = t2._idrref)
-> Seq Scan on tt3 t1 (cost=0.00..1.22 rows=22 width=40)
-> Hash (cost=6.36..6.36 rows=36 width=64)
-> Seq Scan on _reference7x1 t2 (cost=0.00..6.36 rows=36 width=64)
-> Hash (cost=1.12..1.12 rows=12 width=24)
-> Seq Scan on tt2 t3 (cost=0.00..1.12 rows=12 width=24)
*/
/*
Query Text: SELECT
T3._Q_001_F_000RRef,
T3._Q_001_F_001,
T1._Q_001_F_002,
T1._Q_001_F_001RRef,
T2._Fld23
FROM pg_temp.tt3 T1
LEFT OUTER JOIN _Reference7X1 T2
ON (T1._Q_001_F_001RRef = T2._IDRRef)
INNER JOIN pg_temp.tt2 T3
ON (T1._Q_001_F_000RRef = T3._Q_001_F_000RRef)
Hash Join (cost=8.01..9.51 rows=22 width=79) (actual time=0.027..0.037 rows=22 loops=1)
Output: t3._q_001_f_000rref, t3._q_001_f_001, t1._q_001_f_002, t1._q_001_f_001rref, t2._fld23
Hash Cond: (t1._q_001_f_000rref = t3._q_001_f_000rref)
Buffers: shared hit=6, local hit=2
-> Hash Left Join (cost=6.76..8.01 rows=22 width=72) (actual time=0.020..0.025 rows=22 loops=1)
Output: t1._q_001_f_002, t1._q_001_f_001rref, t1._q_001_f_000rref, t2._fld23
Inner Unique: true
Hash Cond: (t1._q_001_f_001rref = t2._idrref)
Buffers: shared hit=6, local hit=1
-> Seq Scan on pg_temp.tt3 t1 (cost=0.00..1.22 rows=22 width=40) (actual time=0.001..0.002 rows=22 loops=1)
Output: t1._q_001_f_000rref, t1._q_001_f_001rref, t1._q_001_f_002
Buffers: local hit=1
-> Hash (cost=6.36..6.36 rows=36 width=64) (actual time=0.016..0.016 rows=36 loops=1)
Output: t2._fld23, t2._idrref
Buckets: 1024 Batches: 1 Memory Usage: 11kB
Buffers: shared hit=6
-> Seq Scan on public._reference7x1 t2 (cost=0.00..6.36 rows=36 width=64) (actual time=0.003..0.011 rows=36 loops=1)
Output: t2._fld23, t2._idrref
Buffers: shared hit=6
-> Hash (cost=1.12..1.12 rows=12 width=24) (actual time=0.005..0.005 rows=12 loops=1)
Output: t3._q_001_f_000rref, t3._q_001_f_001
Buckets: 1024 Batches: 1 Memory Usage: 9kB
Buffers: local hit=1
-> Seq Scan on pg_temp.tt2 t3 (cost=0.00..1.12 rows=12 width=24) (actual time=0.002..0.002 rows=12 loops=1)
Output: t3._q_001_f_000rref, t3._q_001_f_001
Buffers: local hit=1
Settings: enable_mergejoin = 'off', cpu_operator_cost = '0.001'
*/
Ссылки на документацию разработчика
Дополнительно поставляемый модуль auto_dump.