F.4. auto_dump — расширение с хуком ProcessInterrupts#
F.4. auto_dump — расширение с хуком ProcessInterrupts #
F.4.1. Обзор #
auto_dump помогает вам
создать самодостаточную
репродукцию проблемных запросов, которые выполняются
в рабочей среде (например, из 1С).
Когда условие триггера выполняется, расширение записывает:
DDL для таблиц, используемых в запросе (временных и/или постоянных — настраиваемо)
Необязательные дампы данных (операторы INSERT)
Необязательные команды создания индексов
Необязательный текст запроса
Необязательный план(ы) выполнения:
EXPLAINиEXPLAIN (ANALYZE, BUFFERS, WAL, TIMING, SUMMARY)
Дампы записываются в каталог, создаваемый для каждого запроса и называемый:
<PID>-YYYY_MM_DD_hh_mm_ss-<counter>/
Пример файлов:
create.sql createwithdata.sql
Примечание
Планирование дампа и триггер “dump_on_cancel” требуют небольшего патча ядра, который добавляет ProcessInterrupts_hook. Для работы этих функций необходимо применить этот патч и собрать Tantor SE с ним.
F.4.2. Требования #
Tantor SE версии, соответствующей патчам/исходным кодам, с которыми вы производите сборку.
C-инструментарий для сборки расширений Tantor SE.
Основной патч (добавляет
ProcessInterrupts_hook), если хотите:dump-on-cancel (
auto_dump.dump_on_cancel)сбор плана с инструментированием (
auto_dump.dump_plan = onилиauto_dump.dump_on_bad_plan = on)
F.4.3. Включение расширения #
Добавьте в
postgresql.conf(для всего кластера):shared_preload_libraries = 'auto_dump' auto_dump.enable = on auto_dump.output_directory = '/var/lib/postgresql/auto_dump_files/'
Перезапустите Tantor SE:
systemctl restart tantor-se-server-16
В целевой базе данных:
CREATE EXTENSION auto_dump;
F.4.4. Конфигурация (GUCs) #
Все параметры GUC имеют значение SUSET (могут быть установлены суперпользователем во время выполнения, если не указано иное ограничение). Значения по умолчанию соответствуют текущей реализации в коде.
F.4.4.1. Основные параметры (GUC) #
| GUC | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
auto_dump.enable
| bool |
off
| Главный GUC для включения дампирования. |
auto_dump.output_directory
| string |
''
| Каталог, в котором создаются папки дампов (обязательно). |
auto_dump.dump_query
| bool |
on
| Включает исходный текст запроса (в виде блока комментария). |
auto_dump.dump_create
| bool |
on
| Включает операторы создания таблиц. |
auto_dump.dump_indexes
| bool |
on
| Включает операторы создания индексов. |
auto_dump.dump_data
| bool |
on
| Включает данные таблицы (INSERT). |
auto_dump.dump_plan
| bool |
on
|
Включает вывод EXPLAIN и
EXPLAIN ANALYZE. Требуется
инструментирование.
|
F.4.4.2. Параметры сохранения таблиц #
| GUC | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
auto_dump.dump_temporary_tables
| bool |
true
| Сохраняет временные таблицы, на которые ссылается запрос. |
auto_dump.dump_persistent_tables
| bool |
false
| Сохраняет постоянные таблицы, на которые ссылается запрос. |
auto_dump.dump_all_temp_tables
| bool |
false
| Сохраняет все временные таблицы в текущей сессии backend, а не только те, которые были использованы в запросе, вызвавшем триггер. |
F.4.4.3. Триггеры #
| GUC | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
auto_dump.dump_on_query_string
| string |
''
| Если не пусто, выполняет дамп, когда текст запроса содержит эту подстроку или подстроки. |
auto_dump.dump_on_cancel
| bool |
false
| Выполняет дамп при отмене текущего запроса. Требует патча ядра (добавляет ProcessInterrupts_hook). |
auto_dump.dump_on_bad_plan
| bool |
false
| Выполняет дамп, когда выполненный план считается “плохим” (см. пороги ниже). Требуется инструментирование. |
F.4.4.3.1. dump_on_query_string: несколько
подстрок с | #
Вы можете указать несколько альтернатив для подстроки-триггера, разделяя их вертикальной чертой (|):
CREATE TABLE AAA(BBB int, CCC int); SET auto_dump.dump_on_query_string = 'AAA'; -- Triggers (contains 'AAA') - default work SELECT 1 FROM AAA; SET auto_dump.dump_on_query_string = 'AAA|BBB|CCC'; -- Triggers (contains 'AAA' or 'BBB' or 'CCC') SELECT 1 FROM AAA; SELECT BBB FROM AAA; -- Does not trigger (different case): SELECT ccc FROM aaa; -- To match case variants, list them explicitly: SET auto_dump.dump_on_query_string = 'AAA|BBB|CCC|aaa|bbb|ccc';
F.4.4.4. “Пороговые значения "плохого плана"” #
Узел плана считается “плохим” только если
оба включённых порога превышены (логическое И). Вы можете отключить порог, установив его
в значение 0 или ниже.
| GUC | Тип | Значение по умолчанию | Значение |
|---|---|---|---|
auto_dump.bad_plan_count_threshold
| int |
0
|
Абсолютная разница между оценочным и фактическим количеством строк для срабатывания. > 0 включает; <= 0 отключает.
|
auto_dump.bad_plan_percent_threshold
| int |
0
|
Процентное различие для срабатывания. > 0
включает; <= 0 отключает. Процент
вычисляется только если estimated > 0,
чтобы избежать деления на ноль.
|
auto_dump.bad_plan_min_expected_rows
| int |
100
| Минимальный порог оценочного количества строк. Узлы, у которых как оценочное, так и фактическое количество строк ниже порога, игнорируются (подавление шума). |
auto_dump.bad_plan_min_actual_rows
| int |
100
| Минимальное фактическое количество строк (используется вместе с порогом оценочного количества строк). |
Примечание
На загруженных рабочих нагрузках 1С, начните с:
auto_dump.dump_on_bad_plan = on auto_dump.bad_plan_min_expected_rows = 100 auto_dump.bad_plan_min_actual_rows = 100 auto_dump.bad_plan_count_threshold = 1000 auto_dump.bad_plan_percent_threshold = 300
Если в запросах часто встречается estimate = 0, и вы всё равно хотите реагировать на большие абсолютные несоответствия, отключите порог в процентах:
auto_dump.bad_plan_percent_threshold = 0
F.4.5. Режимы срабатывания #
По подстроке: если
auto_dump.dump_on_query_stringявляется непустой строкой и текст запроса содержит её, создаётся дамп.При отмене: если
auto_dump.dump_on_cancel = on, дамп создаётся, когдаpg_cancel_backend()прерывает выполняющийся запрос (требуется патч ядра с ProcessInterrupts_hook).При “плохом плане”: если
auto_dump.dump_on_bad_plan = on, исполнитель проверяет счетчики инструментирования после выполнения и срабатывает, если пороги превышены.
F.4.6. Что выгружается #
create.sql: объекты схемы (таблицы, индексы),ANALYZE, и — в блоке комментария — текстEXPLAIN, еслиdump_plan = onиEXPLAINбыл запрошен без данных.createwithdata.sql: то же, что иcreate.sql, плюс операторыINSERTс сохранёнными строками (когдаdump_data = on).Исходный текст запроса включается в виде блока комментария, когда
dump_query = on.
По умолчанию только временные таблицы выгружаются
(auto_dump.dump_temporary_tables = on,
auto_dump.dump_persistent_tables = off). Включите
сохранение постоянных таблиц, если вам нужно полностью воспроизвести
ситуацию вне исходной сессии.
F.4.7. Каталог вывода и наименование файлов #
Базовый каталог:
auto_dump.output_directory(должен быть доступен для записи пользователем операционной системы сервера базы данных).Каждая выгрузка создает подкаталог:
<PID>-YYYY_MM_DD_hh_mm_ss-<counter>/
Файлы внутри:
create.sql createwithdata.sql
F.4.8. Пример использования (из реальной нагрузки, похожей на 1С) #
У нас есть SQL-запрос, который нам нужно воспроизвести и отладить:
SELECT
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef,
CASE WHEN (T1._Q_000_F_003RRef IN ('\\261\\321\\276\\257\\272\\331\\300wM\\263\\336*q\\031I\\316'::bytea, '\\247\\202\\266$\\366\\301r\\343N\\300\\333\\\\m1\\221\\330'::bytea, '\\235\\352S\\336\\242/$\\372L\\011\\237\\202K\\246\\332n'::bytea)) THEN SUM(T2._Fld33213) WHEN (T1._Q_000_F_003RRef IN ('\\200\\357\\030o\\256\\333\\332W@\\263\\231\\3626\\013\\334t'::bytea)) THEN SUM(T4._Fld33309) END,
T1._Q_000_F_000RRef
FROM pg_temp.tt7 T1
LEFT OUTER JOIN _Document1328_VT33208X1 T2
LEFT OUTER JOIN _Document1328X1 T3
ON (T2._Document1328_IDRRef = T3._IDRRef) AND (T3._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T3._Fld33135RRef) AND (T1._Q_000_F_001RRef = T2._Fld33210RRef) AND (T1._Q_000_F_002RRef = T2._Fld33211RRef) AND (T2._Fld33240 = FALSE)) AND (T2._Fld2488 = CAST(0 AS NUMERIC))
LEFT OUTER JOIN _Document1328_VT33302X1 T4
LEFT OUTER JOIN _Document1328X1 T5
ON (T4._Document1328_IDRRef = T5._IDRRef) AND (T5._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T5._Fld33135RRef) AND (T1._Q_000_F_001RRef = T4._Fld33304RRef) AND (T1._Q_000_F_002RRef = T4._Fld33305RRef) AND (T4._Fld77517 = FALSE)) AND (T4._Fld2488 = CAST(0 AS NUMERIC))
GROUP BY T1._Q_000_F_000RRef,
T1._Q_000_F_003RRef,
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef;
В postgresql.conf включите расширение, укажите каталог для дампов и задайте подстроку, которая должна вызывать дамп для этого запроса:
shared_preload_libraries = 'auto_dump' auto_dump.enable = on auto_dump.output_directory = '/var/lib/postgresql/auto_dump_files/' auto_dump.dump_on_query_string = 'LEFT OUTER JOIN _Document1328_VT33208X1 T2'
Перезапустите службу Tantor SE:
systemctl restart tantor-se-server-16
Создайте расширение в базе данных, в которой выполняется целевой запрос:
-- psql \c erp CREATE EXTENSION auto_dump;
После того как пользователь в 1С инициирует бизнес-действие, запускающее запрос, в каталоге
/var/lib/postgresql/auto_dump_files/ появляется новый подкаталог:
/var/lib/postgresql/auto_dump_files/984933-2025_10_30_15_08_04_04/
Файлы в этом каталоге:
-rw------- 1 postgres postgres 12906 Oct 30 15:08 create.sql -rw------- 1 postgres postgres 13290 Oct 30 15:08 createwithdata.sql
Различие между файлами:
create.sql– DDL (и комментарии с зафиксированным запросом/планом, если включено)createwithdata.sql– всё, что находится вcreate.sqlплюсINSERTоператоры с сохранёнными строками
По умолчанию только временные таблицы выгружаются
(auto_dump.dump_temporary_tables = on). Вы
увидите данные, подобные следующим:
CREATE TEMPORARY TABLE tt7 (
_q_000_f_000rref bytea,
_q_000_f_001rref bytea,
_q_000_f_002rref bytea,
_q_000_f_003rref bytea,
_q_000_f_004 numeric(10,0),
_q_000_f_005 timestamp without time zone,
_q_000_f_006 timestamp without time zone,
_q_000_f_007 timestamp without time zone
);
CREATE INDEX tmpind_0 ON pg_temp.tt7 USING btree (_q_000_f_000rref);INSERT INTO tt7 (_q_000_f_000rref, _q_000_f_001rref, _q_000_f_002rref, _q_000_f_003rref, _q_000_f_004, _q_000_f_005, _q_000_f_006, _q_000_f_007) VALUES (E'\\x98891866dab152db11eedf71f5f2a486',E'\\x83b11866dab152db11ee95becd03e9a6',E'\\x00000000000000000000000000000000',E'\\xb1d1beafbad9c0774db3de2a711949ce',0,'2024-03-12 00:00:00','2024-03-13 00:00:00','2024-03-12 00:00:00');
ANALYZE tt7;
/*
SELECT
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef,
CASE WHEN (T1._Q_000_F_003RRef IN ('\261\321\276\257\272\331\300wM\263\336*q\031I\316'::bytea, '\247\202\266$\366\301r\343N\300\333\\m1\221\330'::bytea, '\235\352S\336\242/$\372L\011\237\202K\246\332n'::bytea)) THEN SUM(T2._Fld33213) WHEN (T1._Q_000_F_003RRef IN ('\200\357\030o\256\333\332W@\263\231\3626\013\334t'::bytea)) THEN SUM(T4._Fld33309) END,
T1._Q_000_F_000RRef
FROM pg_temp.tt7 T1
LEFT OUTER JOIN _Document1328_VT33208X1 T2
LEFT OUTER JOIN _Document1328X1 T3
ON (T2._Document1328_IDRRef = T3._IDRRef) AND (T3._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T3._Fld33135RRef) AND (T1._Q_000_F_001RRef = T2._Fld33210RRef) AND (T1._Q_000_F_002RRef = T2._Fld33211RRef) AND (T2._Fld33240 = FALSE)) AND (T2._Fld2488 = CAST(0 AS NUMERIC))
LEFT OUTER JOIN _Document1328_VT33302X1 T4
LEFT OUTER JOIN _Document1328X1 T5
ON (T4._Document1328_IDRRef = T5._IDRRef) AND (T5._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T5._Fld33135RRef) AND (T1._Q_000_F_001RRef = T4._Fld33304RRef) AND (T1._Q_000_F_002RRef = T4._Fld33305RRef) AND (T4._Fld77517 = FALSE)) AND (T4._Fld2488 = CAST(0 AS NUMERIC))
GROUP BY T1._Q_000_F_000RRef,
T1._Q_000_F_003RRef,
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef;*/
/*
Query Text: SELECT
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef,
CASE WHEN (T1._Q_000_F_003RRef IN ('\\261\\321\\276\\257\\272\\331\\300wM\\263\\336*q\\031I\\316'::bytea, '\\247\\202\\266$\\366\\301r\\343N\\300\\333\\\\m1\\221\\330'::bytea, '\\235\\352S\\336\\242/$\\372L\\011\\237\\202K\\246\\332n'::bytea)) THEN SUM(T2._Fld33213) WHEN (T1._Q_000_F_003RRef IN ('\\200\\357\\030o\\256\\333\\332W@\\263\\231\\3626\\013\\334t'::bytea)) THEN SUM(T4._Fld33309) END,
T1._Q_000_F_000RRef
FROM pg_temp.tt7 T1
LEFT OUTER JOIN _Document1328_VT33208X1 T2
LEFT OUTER JOIN _Document1328X1 T3
ON (T2._Document1328_IDRRef = T3._IDRRef) AND (T3._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T3._Fld33135RRef) AND (T1._Q_000_F_001RRef = T2._Fld33210RRef) AND (T1._Q_000_F_002RRef = T2._Fld33211RRef) AND (T2._Fld33240 = FALSE)) AND (T2._Fld2488 = CAST(0 AS NUMERIC))
LEFT OUTER JOIN _Document1328_VT33302X1 T4
LEFT OUTER JOIN _Document1328X1 T5
ON (T4._Document1328_IDRRef = T5._IDRRef) AND (T5._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T5._Fld33135RRef) AND (T1._Q_000_F_001RRef = T4._Fld33304RRef) AND (T1._Q_000_F_002RRef = T4._Fld33305RRef) AND (T4._Fld77517 = FALSE)) AND (T4._Fld2488 = CAST(0 AS NUMERIC))
GROUP BY T1._Q_000_F_000RRef,
T1._Q_000_F_003RRef,
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef
GroupAggregate (cost=5.02..5.04 rows=1 width=100)
Group Key: t1._q_000_f_000rref, t1._q_000_f_003rref, t1._q_000_f_001rref, t1._q_000_f_002rref
-> Sort (cost=5.02..5.02 rows=1 width=78)
Sort Key: t1._q_000_f_000rref, t1._q_000_f_003rref, t1._q_000_f_001rref, t1._q_000_f_002rref
-> Nested Loop Left Join (cost=0.73..5.00 rows=1 width=78)
-> Nested Loop Left Join (cost=0.39..3.41 rows=1 width=73)
-> Seq Scan on tt7 t1 (cost=0.00..1.01 rows=1 width=68)
-> Nested Loop (cost=0.39..2.39 rows=1 width=56)
Join Filter: ((t1._q_000_f_001rref = t4._fld33304rref) AND (t1._q_000_f_002rref = t4._fld33305rref))
-> Index Only Scan using _document1328_4x1 on _document1328x1 t5 (cost=0.17..1.29 rows=1 width=34)
Index Cond: ((_fld2488 = '0'::numeric) AND (_fld33135rref = t1._q_000_f_000rref))
-> Index Scan using _document1328_vt33302_skx1 on _document1328_vt33302x1 t4 (cost=0.22..0.93 rows=14 width=56)
Index Cond: ((_fld2488 = '0'::numeric) AND (_document1328_idrref = t5._idrref))
Filter: (NOT _fld77517)
-> Nested Loop (cost=0.34..1.58 rows=1 width=56)
Join Filter: ((t1._q_000_f_001rref = t2._fld33210rref) AND (t1._q_000_f_002rref = t2._fld33211rref))
-> Index Only Scan using _document1328_4x1 on _document1328x1 t3 (cost=0.17..1.29 rows=1 width=34)
Index Cond: ((_fld2488 = '0'::numeric) AND (_fld33135rref = t1._q_000_f_000rref))
-> Index Scan using _document1328_vt33208_skx1 on _document1328_vt33208x1 t2 (cost=0.17..0.28 rows=1 width=56)
Index Cond: ((_fld2488 = '0'::numeric) AND (_document1328_idrref = t3._idrref))
Filter: (NOT _fld33240)
*/
/*
Query Text: SELECT
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef,
CASE WHEN (T1._Q_000_F_003RRef IN ('\\261\\321\\276\\257\\272\\331\\300wM\\263\\336*q\\031I\\316'::bytea, '\\247\\202\\266$\\366\\301r\\343N\\300\\333\\\\m1\\221\\330'::bytea, '\\235\\352S\\336\\242/$\\372L\\011\\237\\202K\\246\\332n'::bytea)) THEN SUM(T2._Fld33213) WHEN (T1._Q_000_F_003RRef IN ('\\200\\357\\030o\\256\\333\\332W@\\263\\231\\3626\\013\\334t'::bytea)) THEN SUM(T4._Fld33309) END,
T1._Q_000_F_000RRef
FROM pg_temp.tt7 T1
LEFT OUTER JOIN _Document1328_VT33208X1 T2
LEFT OUTER JOIN _Document1328X1 T3
ON (T2._Document1328_IDRRef = T3._IDRRef) AND (T3._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T3._Fld33135RRef) AND (T1._Q_000_F_001RRef = T2._Fld33210RRef) AND (T1._Q_000_F_002RRef = T2._Fld33211RRef) AND (T2._Fld33240 = FALSE)) AND (T2._Fld2488 = CAST(0 AS NUMERIC))
LEFT OUTER JOIN _Document1328_VT33302X1 T4
LEFT OUTER JOIN _Document1328X1 T5
ON (T4._Document1328_IDRRef = T5._IDRRef) AND (T5._Fld2488 = CAST(0 AS NUMERIC))
ON ((T1._Q_000_F_000RRef = T5._Fld33135RRef) AND (T1._Q_000_F_001RRef = T4._Fld33304RRef) AND (T1._Q_000_F_002RRef = T4._Fld33305RRef) AND (T4._Fld77517 = FALSE)) AND (T4._Fld2488 = CAST(0 AS NUMERIC))
GROUP BY T1._Q_000_F_000RRef,
T1._Q_000_F_003RRef,
T1._Q_000_F_001RRef,
T1._Q_000_F_002RRef
GroupAggregate (cost=5.02..5.04 rows=1 width=100) (actual time=0.125..0.127 rows=1 loops=1)
Output: t1._q_000_f_001rref, t1._q_000_f_002rref, CASE WHEN (t1._q_000_f_003rref = ANY ('{"\\\\xb1d1beafbad9c0774db3de2a711949ce","\\\\xa782b624f6c172e34ec0db5c6d3191d8","\\\\x9dea53dea22f24fa4c099f824ba6da6e"}'::bytea[])) THEN sum(t2._fld33213) WHEN (t1._q_000_f_003rref = '\\x80ef186faedbda5740b399f2360bdc74'::bytea) THEN sum(t4._fld33309) ELSE NULL::numeric END, t1._q_000_f_000rref, t1._q_000_f_003rref
Group Key: t1._q_000_f_000rref, t1._q_000_f_003rref, t1._q_000_f_001rref, t1._q_000_f_002rref
Buffers: shared hit=20, local hit=1
-> Sort (cost=5.02..5.02 rows=1 width=78) (actual time=0.113..0.114 rows=1 loops=1)
Output: t1._q_000_f_001rref, t1._q_000_f_002rref, t1._q_000_f_000rref, t1._q_000_f_003rref, t2._fld33213, t4._fld33309
Sort Key: t1._q_000_f_000rref, t1._q_000_f_003rref, t1._q_000_f_001rref, t1._q_000_f_002rref
Sort Method: quicksort Memory: 25kB
Buffers: shared hit=20, local hit=1
-> Nested Loop Left Join (cost=0.73..5.00 rows=1 width=78) (actual time=0.097..0.099 rows=1 loops=1)
Output: t1._q_000_f_001rref, t1._q_000_f_002rref, t1._q_000_f_000rref, t1._q_000_f_003rref, t2._fld33213, t4._fld33309
Buffers: shared hit=20, local hit=1
-> Nested Loop Left Join (cost=0.39..3.41 rows=1 width=73) (actual time=0.074..0.075 rows=1 loops=1)
Output: t1._q_000_f_001rref, t1._q_000_f_002rref, t1._q_000_f_003rref, t1._q_000_f_000rref, t4._fld33309
Buffers: shared hit=12, local hit=1
-> Seq Scan on pg_temp.tt7 t1 (cost=0.00..1.01 rows=1 width=68) (actual time=0.008..0.009 rows=1 loops=1)
Output: t1._q_000_f_000rref, t1._q_000_f_001rref, t1._q_000_f_002rref, t1._q_000_f_003rref, t1._q_000_f_004, t1._q_000_f_005, t1._q_000_f_006, t1._q_000_f_007
Buffers: local hit=1
-> Nested Loop (cost=0.39..2.39 rows=1 width=56) (actual time=0.063..0.064 rows=0 loops=1)
Output: t4._fld33309, t4._fld33304rref, t4._fld33305rref, t5._fld33135rref
Join Filter: ((t1._q_000_f_001rref = t4._fld33304rref) AND (t1._q_000_f_002rref = t4._fld33305rref))
Rows Removed by Join Filter: 7
Buffers: shared hit=12
-> Index Only Scan using _document1328_4x1 on public._document1328x1 t5 (cost=0.17..1.29 rows=1 width=34) (actual time=0.030..0.030 rows=1 loops=1)
Output: t5._fld2488, t5._fld33135rref, t5._idrref
Index Cond: ((t5._fld2488 = '0'::numeric) AND (t5._fld33135rref = t1._q_000_f_000rref))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Scan using _document1328_vt33302_skx1 on public._document1328_vt33302x1 t4 (cost=0.22..0.93 rows=14 width=56) (actual time=0.022..0.030 rows=7 loops=1)
Output: t4._document1328_idrref, t4._fld2488, t4._keyfield, t4._lineno33303, t4._fld33304rref, t4._fld33305rref, t4._fld33306rref, t4._fld33307rref, t4._fld33308, t4._fld33309, t4._fld33310rref, t4._fld33311, t4._fld33312rref, t4._fld33313, t4._fld33314rref, t4._fld33315rref, t4._fld112251rref, t4._fld33316, t4._fld33317, t4._fld33318, t4._fld33319, t4._fld33320, t4._fld33321, t4._fld33322, t4._fld33323, t4._fld33325rref, t4._fld101275, t4._fld77517, t4._fld77518rref, t4._fld77519, t4._fld33324rref, t4._fld77520rref, t4._fld101276rref, t4._fld81551, t4._fld88569rref, t4._fld112252, t4._fld112253
Index Cond: ((t4._fld2488 = '0'::numeric) AND (t4._document1328_idrref = t5._idrref))
Filter: (NOT t4._fld77517)
Buffers: shared hit=8
-> Nested Loop (cost=0.34..1.58 rows=1 width=56) (actual time=0.021..0.022 rows=1 loops=1)
Output: t2._fld33213, t2._fld33210rref, t2._fld33211rref, t3._fld33135rref
Join Filter: ((t1._q_000_f_001rref = t2._fld33210rref) AND (t1._q_000_f_002rref = t2._fld33211rref))
Buffers: shared hit=8
-> Index Only Scan using _document1328_4x1 on public._document1328x1 t3 (cost=0.17..1.29 rows=1 width=34) (actual time=0.005..0.005 rows=1 loops=1)
Output: t3._fld2488, t3._fld33135rref, t3._idrref
Index Cond: ((t3._fld2488 = '0'::numeric) AND (t3._fld33135rref = t1._q_000_f_000rref))
Heap Fetches: 0
Buffers: shared hit=4
-> Index Scan using _document1328_vt33208_skx1 on public._document1328_vt33208x1 t2 (cost=0.17..0.28 rows=1 width=56) (actual time=0.014..0.014 rows=1 loops=1)
Output: t2._document1328_idrref, t2._fld2488, t2._keyfield, t2._lineno33209, t2._fld33210rref, t2._fld33211rref, t2._fld33212, t2._fld33213, t2._fld33214rref, t2._fld33215_type, t2._fld33215_rtref, t2._fld33215_rrref, t2._fld33216rref, t2._fld33217rref, t2._fld33218, t2._fld33219, t2._fld33220, t2._fld33221, t2._fld33222, t2._fld33223, t2._fld33224, t2._fld33225, t2._fld33226_type, t2._fld33226_rtref, t2._fld33226_rrref, t2._fld33227_type, t2._fld33227_rtref, t2._fld33227_rrref, t2._fld33236_type, t2._fld33236_rtref, t2._fld33236_rrref, t2._fld33229, t2._fld33230rref, t2._fld33231, t2._fld33232rref, t2._fld33233_type, t2._fld33233_rtref, t2._fld33233_rrref, t2._fld33234_type, t2._fld33234_rtref, t2._fld33234_rrref, t2._fld33235_type, t2._fld33235_rtref, t2._fld33235_rrref, t2._fld33237, t2._fld33238, t2._fld33239rref, t2._fld33240, t2._fld33241rref, t2._fld33242rref, t2._fld77511, t2._fld77512, t2._fld77513, t2._fld88563rref, t2._fld88564rref, t2._fld104367, t2._fld104368, t2._fld112249, t2._fld81859
Index Cond: ((t2._fld2488 = '0'::numeric) AND (t2._document1328_idrref = t3._idrref))
Filter: (NOT t2._fld33240)
Buffers: shared hit=4
Settings: max_parallel_workers_per_gather = '0', effective_io_concurrency = '128', maintenance_io_concurrency = '128', random_page_cost = '1.1', from_collapse_limit = '20', join_collapse_limit = '20', max_parallel_workers = '13', hash_mem_multiplier = '8', temp_buffers = '189MB', work_mem = '378MB', effective_cache_size = '279GB', selectivity_model = '1c', enable_mergejoin = 'off', cpu_operator_cost = '0.001'
*/
F.4.9. Настройка и рекомендации #
Шумные среды (1С): используйте пороги для подавления мелких узлов:
auto_dump.dump_on_bad_plan = on auto_dump.bad_plan_min_expected_rows = 100 auto_dump.bad_plan_min_actual_rows = 100 auto_dump.bad_plan_count_threshold = 1000 auto_dump.bad_plan_percent_threshold = 300
Если у многих планов
estimate = 0и вы всё же хотите отлавливать их по абсолютной ошибке, отключите порог в процентах:auto_dump.bad_plan_percent_threshold = 0
Чтобы ограничить объем дампа во время диагностики:
auto_dump.dump_plan = off auto_dump.dump_persistent_tables = off auto_dump.dump_all_temp_tables = off
F.4.10. Устранение неполадок #
Дампы не отображаются:
Проверьте, что
auto_dump.enable = on, а также чтоauto_dump.output_directoryустановлен и доступен для записи.Убедитесь, что
shared_preload_librariesвключаетauto_dump, и сервер был перезапущен.Проверьте, действительно ли выполнено условие триггера (подстрока / отмена / неверный план).
Сбой сервера при отмене или дампе плана:
Убедитесь, что вы запускаете сервер, собранный с патчем
ProcessInterrupts_hook.
Слишком много дампов:
Увеличьте пороги и пределы (смотрите раздел конфигурации).
Используйте триггер по подстроке для точечного срабатывания при анализе проблемы (
auto_dump.dump_on_query_string).
Постоянные таблицы отсутствуют в дампах:
Установите
auto_dump.dump_persistent_tables = on.