Резкое замедление получения остатков по регистру бухгалтерии в 1С на PostgreSQL: как найти причину и быстро исправить?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

В процессе эксплуатации крупных и средних информационных баз на платформе 1С:Предприятие 8.3 в связке с СУБД PostgreSQL специалисты часто сталкиваются с загадочным явлением: запросы к виртуальным таблицам остатков и оборотов регистра бухгалтерии начинают работать крайне медленно, начиная с некоторой «проблемной даты». До этой даты остатки получаются мгновенно (за доли секунды), а после неё — выполнение запроса затягивается на минуты.

Рассмотрим природу этой проблемы, проанализируем, почему стандартные средства обслуживания не всегда помогают, и разберем наиболее эффективный программный метод восстановления производительности.

Симптомы и диагностика проблемы

Выясним, как проявляется данная аномалия. Типичная ситуация выглядит следующим образом: при выполнении запроса к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Остатки на определенную дату (например, 10 мая) система отрабатывает штатно. Однако, если изменить параметр даты всего на одну секунду вперед, время выполнения возрастает в десятки раз. При этом физических записей в регистре на эту секунду может и не быть.

Проанализируем основные признаки:

  1. Проблема возникает спонтанно, без обновлений конфигурации или платформы.
  2. Реиндексация таблиц и стандартный VACUUM ANALYZE средствами СУБД не приносят результата.
  3. Выгрузка в .dt и загрузка обратно «лечит» базу, так как при этом происходит полная пересборка таблиц итогов.
  4. Полная реструктуризация таблиц в режиме «Тестирование и исправление» помогает, но требует монопольного доступа и длительной остановки работы пользователей.

Посмотрим на пример кода, который в проблемной базе может выполняться недопустимо долго:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ХозрасчетныйОстатки.Счет,
    |   ХозрасчетныйОстатки.СуммаОстаток
    |ИЗ
    |   РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, , , ) КАК ХозрасчетныйОстатки";

// Если ДатаОстатков = '20240416103945', выполняется 2 секунды
// Если ДатаОстатков = '20240416103946', выполняется 60 секунд
Запрос.УстановитьПараметр("ДатаОстатков", Объект.НужнаяДата);
Результат = Запрос.Выполнить();

Почему это происходит? Взгляд «под капот»

Разберем основные причины деградации производительности 1С на PostgreSQL в данном контексте. Главная проблема кроется в особенностях работы планировщика запросов PostgreSQL и механизма хранения итогов в 1С.

1. Раздувание (Bloat) таблиц итогов. Таблицы итогов (_AccRgTotals) в 1С подвергаются постоянным операциям UPDATE и INSERT. В PostgreSQL из-за механизма MVCC (многоверсионность) при каждом обновлении строки создается её новая версия, а старая помечается как «мертвая». Если процесс очистки (autovacuum) не успевает обрабатывать эти изменения, таблица «раздувается», и планировщик может решить, что полное сканирование таблицы (Sequential Scan) будет эффективнее использования индекса.

2. Некорректная статистика. PostgreSQL собирает статистику распределения данных в колонках. Если данные в регистре распределены неравномерно (например, после определенной даты плотность записей резко меняется), планировщик может построить неоптимальный план запроса. Реструктуризация сбрасывает эту статистику и пересоздает индексы «с чистого листа».

3. Аномальные даты. Одной из скрытых причин может быть наличие в базе записей с «будущими» датами (например, документ от 2099 года). 1С хранит итоги на актуальную дату, и наличие таких записей заставляет систему выполнять избыточные вычисления при получении текущих остатков.

Эффективное решение: программный пересчет итогов

Как показывает практика, существует способ «починить» итоги значительно быстрее, чем через полную реструктуризацию всей информационной базы. Рассмотрим метод программного управления итогами регистра бухгалтерии. Суть метода заключается в принудительном отключении использования итогов, что физически очищает соответствующие таблицы БД, и их последующем включении с полным пересчетом.

Рассмотрим по шагам выполнение этой операции для регистра Хозрасчетный:


Процедура ВосстановитьПроизводительностьИтогов() Экспорт
    
    Регистр = РегистрыБухгалтерии.Хозрасчетный;
    
    // Шаг 1: Полностью отключаем использование итогов. 
    // Это приводит к физической очистке таблиц итогов в PostgreSQL.
    Регистр.УстановитьИспользованиеИтогов(Ложь);
    Регистр.УстановитьИспользованиеТекущихИтогов(Ложь);
    
    // Шаг 2: Включаем использование итогов обратно.
    // Платформа создаст пустые структуры, готовые к заполнению.
    Регистр.УстановитьИспользованиеИтогов(Истина);
    Регистр.УстановитьИспользованиеТекущихИтогов(Истина);
    
    // Шаг 3: Выполняем полный пересчет. 
    // Система заново рассчитает данные на основе записей регистра (движений).
    Регистр.ПересчитатьИтоги();
    Регистр.ПересчитатьТекущиеИтоги();
    
    Сообщить("Пересчет итогов завершен успешно!");
    
КонецПроцедуры

Важный нюанс: Этот метод работает гораздо эффективнее штатного «Тестирования и исправления», так как команда УстановитьИспользованиеИтогов(Ложь) выполняет операцию, аналогичную TRUNCATE или массовому удалению записей в таблицах итогов, что радикально устраняет проблему «раздувания» (bloat) и фрагментации индексов именно для этого объекта.

Дополнительные меры по настройке PostgreSQL

Проанализируем, что еще можно сделать на уровне системного администрирования, чтобы проблема не повторялась:

Резюме

Если вы столкнулись с резким замедлением запросов к итогам регистра бухгалтерии после конкретной даты, не спешите запускать полную реструктуризацию базы на много часов. Сначала проверьте базу на наличие документов с ошибочными датами в далеком будущем. Если их нет, воспользуйтесь приведенным выше программным кодом для сброса и пересчета итогов. В большинстве случаев это решает проблему за считанные минуты, возвращая производительность системы к исходным показателям.

← На главную