При оптимизации высоконагруженных информационных баз и проведении регламентных процедур (таких как свертка базы, массовая загрузка данных или перенос остатков) разработчики и администраторы 1С сталкиваются с низкоуровневыми механизмами платформы. Рассмотрим подробно, как устроен механизм хранения регистров накопления на уровне СУБД, выясним причины расхождений в интерфейсах управления итогами, разберем назначение служебных полей настроечных таблиц и научимся грамотно управлять итогами программно.
Для каждого регистра накопления в зависимости от его вида (остатки или обороты) платформа 1С:Предприятие создает на уровне СУБД набор связанных физических таблиц. Проанализируем назначение каждой из них:
_AccumRg<n>) — содержит непосредственные записи, формируемые документами. Здесь хранятся ссылка на регистратор, номер строки, период, вид движения (приход/расход для регистров остатков), а также значения всех измерений, ресурсов и реквизитов регистра._AccumRgT<n>) — используется для регистров остатков и хранит срезы рассчитанных остатков на начало каждого месяца. Если для регистра оборотов включена периодичность итогов, в ней фиксируются агрегированные обороты по периодам._AccumRgTn<n>) — предназначена для регистров остатков. Она содержит актуальное состояние остатков на самую крайнюю точку актуальности («бесконечность»). При оперативном проведении документов обращение к этой таблице позволяет мгновенно получить текущие остатки без необходимости считывания движений за последний неполный месяц._AccumRgOpt или _AccumRgOpt<n>) — служебная таблица, хранящая системную конфигурацию: признак включения итогов, даты границ рассчитанных периодов и статус использования механизма разделения итогов._AccumRgAgg*, _AccumRgBf, _AccumRgDl) — формируются для регистров оборотов, если включен механизм использования агрегатов для ускорения аналитических запросов.Разберем ситуацию, когда стандартная форма управления итогами платформы 1С выглядит не так, как в статьях или руководствах. В платформе 1С:Предприятие 8.3 диалог «Управление итогами» реализован в двух вариантах в зависимости от режима запуска клиента:
Для открытия полнофункционального интерфейса достаточно запустить базу данных в режиме управляемого приложения.
_UseTotals в таблице _AccumRgOptВыясним причину, почему при включенном расчете итогов в таблице настроек _AccumRgOpt поле _UseTotals может содержать значение 0.
На уровне структуры данных платформы 1С поле _UseTotals не является стандартным логическим флагом (где 1 — Истина, 0 — Ложь), а отражает маску ограничений или статус отключения функционала:
_UseTotals = 0 (или 0x00) означает, что ограничения отсутствуют, то есть итоги включены и активно используются._UseTotals = 1 фиксирует, что итоги для регистра отключены.Помимо признака использования, в этой же таблице хранятся поля _Period (дата, по которую рассчитаны месячные итоги) и _ActualPeriod (точка актуальности текущих итогов).
Рассмотрим по шагам, как работают методы менеджеров регистров накопления и как их применять на практике.
При массовой загрузке данных, свертке или проведении исторических документов постоянный пересчет таблиц _AccumRgT и _AccumRgTn приводит к огромным накладным расходам и взаимным блокировкам. Для ускорения записи итоги временно отключают:
// Отключение итогов перед массовой операцией
РегистрыНакопления.ТоварыНаСкладах.УстановитьИспользованиеИтогов(Ложь);
// Выполнение тяжелой пакетной записи движений
// ...
// Включение итогов обратно
РегистрыНакопления.ТоварыНаСкладах.УстановитьИспользованиеИтогов(Истина);
Проанализируем, как работает метод УстановитьИспользованиеИтогов(Истина):
Ложь платформа перестает обновлять таблицы _AccumRgT и _AccumRgTn, записывая строки только в _AccumRg. При этом в системной информации фиксируется факт отключения и дата первого измененного движения.Истина платформа не выполняет полное сканирование всей таблицы с начала времен. Она вычисляет диапазон дат, в котором происходили модификации движений во время отключения, и выполняет дифференциальный (инкрементальный) пересчет, накатывая дельту изменений в таблицы итогов.Разберем разницу между доступными инструментами восстановления итогов:
УстановитьИспользованиеИтогов(Истина): выполняет только частичный пересчет затронутых периодов. Если структура итогов была нарушена прямыми воздействиями на СУБД или сбоями транзакций, метод не гарантирует устранение расхождений во всей исторической глубине.РегистрыНакопления[<ИмяРегистра>].ПересчитатьИтоги(): метод менеджера регистра накопления, который принудительно и полностью очищает таблицы _AccumRgT и _AccumRgTn и заново формирует их по всем данным из _AccumRg. Это штатный способ гарантированного пересчета без необходимости блокировки всей системы.Посмотрим на пример комплексного скрипта пересчета итогов для регистра:
// Устанавливаем признак активности и выполняем полный пересчет
МенеджерРегистра = РегистрыНакопления.ОстаткиТоваров;
МенеджерРегистра.УстановитьИспользованиеИтогов(Истина);
МенеджерРегистра.ПересчитатьИтоги();
Рассмотрим передовые механизмы управления глубиной итогов, появившиеся в платформе 8.3:
УстановитьМинимальныйПериодРассчитанныхИтогов()): позволяет сдвинуть нижнюю границу хранения итогов вперед (например, оставить срезы только за последние 2–3 года). Записи из _AccumRgT старше указанной даты физически удаляются из базы. Если пользователю потребуется остаток на старую дату, платформа рассчитает его по движениям «на лету», но размер базы данных в СУБД существенно сократится.УстановитьМаксимальныйПериодРассчитанныхИтогов()): ограничивает расчет итогов в будущее, предотвращая раздувание таблиц из-за случайных документов с ошибочными датами._AccumRgT и _AccumRgTn часто остаются строки с нулевыми значениями ресурсов. Со временем их количество достигает десятков миллионов строк, что сильно замедляет работу запросов к виртуальным таблицам остатков. Полный пересчет итогов через ПересчитатьИтоги() или ТиИ очищает такие строки.Проанализируем заключительный этап оптимизации. После выполнения процедур свертки, отключения/включения итогов или их полного пересчета на стороне MS SQL Server возникает высокая степень фрагментации индексов и потеря актуальности статистики распределения данных. Платформа 1С не запускает реиндексацию СУБД автоматически.
Для восстановления производительности после масштабных манипуляций с итогами необходимо выполнить регламентные скрипты на стороне СУБД:
-- Перестроение индексов таблиц движений и итогов
ALTER INDEX ALL ON _AccumRg1234 REBUILD;
ALTER INDEX ALL ON _AccumRgT1234 REBUILD;
ALTER INDEX ALL ON _AccumRgTn1234 REBUILD;
-- Обновление статистики с полным сканированием
UPDATE STATISTICS _AccumRg1234 WITH FULLSCAN;
UPDATE STATISTICS _AccumRgT1234 WITH FULLSCAN;
UPDATE STATISTICS _AccumRgTn1234 WITH FULLSCAN;
Выполнение этих шагов обеспечивает стабильную и быструю работу регистров накопления даже при экстремальных объемах учетных данных.