В процессе эксплуатации систем на базе 1С:Предприятие и PostgreSQL администраторы часто сталкиваются с ситуацией, когда стандартное регламентное обслуживание всей базы данных занимает слишком много времени или вызывает избыточную нагрузку на дисковую подсистему. Нередко возникает необходимость «полечить» только одну конкретную таблицу, которая подверглась массовому изменению или удалению данных (например, после очистки огромного регистра сведений или итогов). В этой статье мы рассмотрим, как автоматизировать обслуживание отдельных объектов базы данных с помощью скриптов и встроенных инструментов PostgreSQL.
Прежде чем перейти к практике, проанализируем причины. В PostgreSQL используется механизм MVCC (многоверсионность), из-за которого при обновлении (UPDATE) или удалении (DELETE) строк старые версии физически остаются в файлах базы данных. Если таблица большая и данные в ней меняются часто, возникает «раздувание» (bloat). Стандартный VACUUM всей базы может длиться часами, в то время как целевое обслуживание проблемной таблицы занимает минуты. Рассмотрим несколько способов решения этой задачи.
Самый гибкий способ — это запуск SQL-команды через терминальный клиент psql. Это позволяет передать точную команду VACUUM или ANALYZE для конкретного объекта. Разберем пример рабочего BAT-файла для Windows, который можно поставить в планировщик задач.
Посмотрим на пример кода:
chcp 1251
set PGUSER=postgres
set PGPASSWORD=ваш_пароль
set PGDATABASE=название_базы
set PGHOST=localhost
set PGPORT=5432
rem Путь к psql (укажите свою версию)
set PSQL_PATH="C:\Program Files\PostgreSQL\15\bin\psql.exe"
rem Выполнение полной очистки конкретной таблицы 1С
%PSQL_PATH% -U %PGUSER% -h %PGHOST% -p %PGPORT% -d %PGDATABASE% -c "VACUUM (VERBOSE, FULL, ANALYZE) public._InfoReg12345;"
В данном скрипте мы используем команду VACUUM FULL, которая полностью пересобирает таблицу и возвращает место операционной системе. Важный нюанс: помните, что VACUUM FULL блокирует таблицу полностью (Access Exclusive Lock). Пока идет процесс, пользователи 1С не смогут работать с данными этой таблицы.
Многие администраторы привыкли использовать vacuumdb для всей базы, но не все знают, что утилита поддерживает ключ -t для выбора конкретной таблицы. Это более «чистый» способ, так как он корректно обрабатывает параметры подключения.
Разберем по шагам, как выполнить обслуживание через командную строку:
VACUUM выполните команду:
vacuumdb -t "public._accumreg100" --analyze --dbname=zup_db
reindexdb -t "public._accumreg100" --dbname=zup_db
Преимущество этого метода в том, что вы можете указать несколько таблиц сразу, просто добавив еще один ключ -t. Это удобно, если вам нужно обслужить группу связанных регистров.
Начиная с PostgreSQL 12, мы можем использовать режим CONCURRENTLY. Это критически важно для систем 1С, работающих в режиме 24/7. Выясним причину популярности этого метода: он позволяет перестраивать индексы, не запрещая запись в таблицу.
Проанализируем пример SQL-запроса:
-- Выполняется внутри psql или через PGAdmin
REINDEX TABLE CONCURRENTLY public._inforeg4567;
Хотя этот процесс занимает больше времени и создает дополнительную нагрузку на CPU/Disk, он позволяет избежать ошибки «Конфликт блокировок» у пользователей. Однако стоит помнить, что VACUUM FULL не имеет режима CONCURRENTLY. Если вам нужно именно сжать таблицу без блокировок, рекомендуем обратить внимание на расширение pg_repack.
В базах данных 1С имена таблиц в PostgreSQL выглядят как _InfoReg123 или _Document45. Чтобы понять, какую именно таблицу нужно обслужить, мы можем воспользоваться внутренней таблицей соответствий имен, которую создает 1С.
Рассмотрим подробнее, как найти системное имя таблицы «РегистрНакопления.Продажи»:
SELECT * FROM v8_table_names WHERE "Table_Name" LIKE '%Продажи%';
После получения точного имени (например, _accumreg789), вы можете подставить его в свои скрипты автоматизации. Это позволит сделать ваше обслуживание «умным».
Чтобы не хранить пароли в открытом виде в BAT-файлах и сделать процесс кроссплатформенным, разберем вариант с созданием хранимой процедуры прямо в базе данных. Вы можете создать функцию на языке plpgsql, которая будет принимать имя таблицы и выполнять необходимые действия.
Посмотрим на пример структуры функции:
CREATE OR REPLACE PROCEDURE maintenance_specific_table(tbl_name TEXT)
LANGUAGE plpgsql
AS $$
BEGIN
EXECUTE format('VACUUM (ANALYZE) %I', tbl_name);
EXECUTE format('REINDEX TABLE %I', tbl_name);
END;
$$;
Вызывать такую процедуру можно одной короткой командой CALL maintenance_specific_table('public._Document10');, что значительно упрощает интеграцию с любыми внешними планировщиками или даже запуск из самой среды 1С через ВнешниеИсточникиДанных.
Подводя итог, выделим основные правила обслуживания конкретных таблиц:
Таким образом, точечное обслуживание позволяет поддерживать высокую производительность 1С без необходимости останавливать работу всей организации для профилактики всей базы целиком.