Как эффективно пересчитать итоги в 1С при работе с большими объемами данных?

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

Работа с регистрами накопления, в которых количество записей исчисляется миллионами ежемесячно, рано или поздно приводит к проблеме катастрофического замедления пересчета итогов. Стандартные процедуры могут зависать на часы или даже дни, парализуя работу системы. В рамках данной статьи мы подробно разберем, как справиться с этой задачей, проанализируем различные подходы — от штатных методов платформы 1С до глубокой оптимизации на уровне SQL Server.

Разбор проблемы: почему стандартный пересчет не справляется?

Когда мы запускаем ПересчитатьИтоги(), система выполняет полную очистку таблиц итогов (AccumRgT) и их повторное заполнение на основе таблицы движений. На объемах в 20–30 миллионов строк эта операция создает колоссальную нагрузку на дисковую подсистему и файл лога транзакций SQL. Мы часто сталкиваемся с тем, что расчет "зависает" именно из-за нехватки ресурсов для обработки одной гигантской транзакции или из-за неэффективного использования временных таблиц.

Способ 1. Инкрементальный расчет через установку периода

Рассмотрим более мягкий способ управления итогами. Вместо полной очистки мы можем двигать границу рассчитанных итогов последовательно. Проанализируем разницу: метод УстановитьПериодРассчитанныхИтогов() выполняет расчет только за указанный интервал относительно текущей границы. Если мы будем двигать дату помесячно, 1С выполнит серию небольших транзакций, что гораздо безопаснее для стабильности системы.

Посмотрим на пример кода, который позволяет делать это итерационно:


ТекущаяДатаГраницы = РегистрыНакопления.ИмяВашегоРегистра.ПолучитьПериодРассчитанныхИтогов();
КонечнаяДата = '20231231'; // Например, конец года

Пока ТекущаяДатаГраницы < КонечнаяДата Цикл
    ТекущаяДатаГраницы = ДобавитьМесяц(ТекущаяДатаГраницы, 1);
    РегистрыНакопления.ИмяВашегоРегистра.УстановитьПериодРассчитанныхИтогов(ТекущаяДатаГраницы);
    Сообщить("Итоги рассчитаны по: " + ТекущаяДатаГраницы);
КонецЦикла;

Способ 2. "Быстрая очистка" итогов через программное отключение

Один из самых эффективных советов, прозвучавших в обсуждении, — это принудительная очистка таблиц итогов перед началом расчета. Если мы просто отключим использование итогов, 1С отправит запрос TRUNCATE TABLE к соответствующим таблицам в SQL Server. Это происходит мгновенно.

Разберем по шагам алгоритм действий:

  1. Отключаем итоги: это очистит физические таблицы итогов AccumRgT.
  2. Устанавливаем минимальный период: сбрасываем границу рассчитанных итогов в "ноль".
  3. Включаем итоги: таблицы создаются заново, но они пустые.
  4. Устанавливаем нужный период: запускаем расчет с чистого листа.

Проанализируем программную реализацию этого метода:


// Шаг 1: Полное отключение итогов (эквивалентно очистке таблиц на SQL)
РегистрыНакопления.ИмяРегистра.УстановитьИспользованиеИтогов(Ложь);

// Шаг 2: Сброс текущих итогов и периода
РегистрыНакопления.ИмяРегистра.УстановитьИспользованиеТекущихИтогов(Ложь);
РегистрыНакопления.ИмяРегистра.УстановитьМаксимальныйПериодРассчитанныхИтогов('00010101');

// Шаг 3: Включение механизмов обратно
РегистрыНакопления.ИмяРегистра.УстановитьИспользованиеИтогов(Истина);
РегистрыНакопления.ИмяРегистра.УстановитьИспользованиеТекущихИтогов(Истина);

// Шаг 4: Установка новой границы расчета (уже на чистые таблицы)
РегистрыНакопления.ИмяРегистра.УстановитьПериодРассчитанныхИтогов(РабочаяДата);

Способ 3. Оптимизация на уровне SQL Server

Если программные методы 1С все еще работают медленно, нам необходимо заглянуть "под капот" СУБД. Выясним основные причины торможения на уровне SQL:

Настройка TempDB. При расчете итогов 1С создает множество временных таблиц. Выясним, как оптимизировать этот процесс: вынесите файлы TempDB на самый быстрый доступный диск (желательно NVMe) и разделите его на несколько файлов одинакового размера (обычно по количеству ядер процессора, но не более 8).

Модель восстановления (Recovery Model). Пересчет миллионов строк генерирует гигабайты логов. Перед началом массового пересчета обязательно переведите базу данных в режим Simple (Простая модель восстановления). Это предотвратит разрастание файла .ldf и значительно ускорит операции записи.

Управление индексами. Посмотрим на структуру таблиц: итоги имеют кластерные и некластерные индексы. При массовой вставке данных обновление индексов занимает до 50% времени. В некоторых случаях оправдано отключение некластерных индексов перед расчетом и их последующая пересборка (Rebuild) после завершения процесса.

Способ 4. Использование режима разделения итогов

Проанализируем свойство Разделение итогов в Конфигураторе. Этот механизм создан для уменьшения блокировок при высоконагруженной записи (создается таблица AccumRgChng). Однако при массовом расчете он может вносить дополнительные накладные расходы. Если вы планируете разовый пересчет огромного массива данных, попробуйте временно отключить разделение итогов для целевого регистра, произвести расчет и включить его снова.

Способ 5. Фоновая обработка партиями

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

Способ 6. Борьба с "нулевыми" остатками

Выясним причину избыточного объема таблиц итогов. Часто в регистрах накапливаются записи, которые в сумме дают ноль (оборот "приход-расход" закрылся в ноль). Если в конфигурации не настроена очистка пустых итогов, таблицы будут хранить эти записи вечно, замедляя каждый последующий расчет. Убедитесь, что у вас включена опция удаления движений с нулевыми значениями, или проведите регламентную очистку таких записей перед началом глобального пересчета.

Подведем итог: для успешного пересчета больших данных мы рекомендуем комбинированный подход. Сначала оптимизируем SQL (TempDB и Simple recovery), затем выполняем программную очистку таблиц через УстановитьИспользованиеИтогов(Ложь) и завершаем процесс инкрементальным расчетом по месяцам, чтобы контролировать нагрузку на систему.

← На главную