Администраторы баз данных и разработчики 1С при анализе таблиц на SQL-сервере (например, через SSMS) иногда сталкиваются с пугающей картиной: в таблицах итогов регистров накопления обнаруживаются миллионы записей с датами из далекого прошлого (2001 год) и далекого будущего (5999 год). При этом в базе данных включено стандартное смещение дат на 2000 лет. Подобные аномалии приводят к катастрофическому раздуванию таблиц СУБД, замедлению работы запросов и зависанию регламентных операций.
В этой статье мы подробно разберем природу этого явления, выясним, почему возникают такие записи, как уязвимости в коде типовых конфигураций (таких как ERP, Комплексная автоматизация или Управление торговлей) способствуют этой проблеме, и рассмотрим пошаговые методы полной очистки и оптимизации таблиц итогов.
Для начала проанализируем, откуда берутся эти даты в таблицах СУБД при использовании смещения дат (+2000 лет):
_AccumRgT абсолютно нормально и заложено в архитектуру платформы. На эту дату система рассчитывает остатки «будущего», чтобы они всегда были позже любого реального документа.Механизм расчета итогов регистров накопления остатков устроен так, что платформа хранит остатки помесячно. Если в регистр записывается движение с периодом 01.01.0001 (в SQL — 2001 год), система считает себя обязанной рассчитать и хранить остатки на конец каждого месяца, начиная с 1-го года нашей эры и до текущего момента (то есть за 2000 лет!).
Даже если физический баланс по этим записям в итоге сворачивается в ноль, в таблице итогов _AccumRgT генерируются тысячи «пустых» (нулевых) записей для каждого месяца за последние два тысячелетия. Ситуация усугубляется механизмом разделения итогов (Splitter): для исключения транзакционных блокировок платформа плодит дубли строк с разными значениями разделителя (поле _DimHash или _Splitter). В результате таблица итогов разрастается до гигантских размеров, перегружая память и дисковую подсистему СУБД.
Рассмотрим, как пустая дата может незаметно попасть в регистр. Типичным примером является регистр РасчетыСПоставщиками в конфигурациях на базе ERP / КА / УТ. Проанализируем фрагмент запроса формирования движений:
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| КОНЕЦПЕРИОДА(&ДатаПлатежа, День) КАК Период,
| &Период КАК ДатаРегистратора,
| &ДатаПлатежа КАК ДатаПлатежа,
...
Если в документе-регистраторе (например, в документе Корректировка поступления или Корректировка долга) реквизит ДатаПлатежа оказался незаполненным, то функция КОНЕЦПЕРИОДА(&ДатаПлатежа, День) вернет пустую дату 01.01.0001. Платформа запишет движение в регистр накопления именно этой пустой датой.
В старых релизах конфигураций проверка заполнения даты платежа при определенных хозяйственных операциях могла отсутствовать либо ее могли случайно обойти программно с помощью внешних обработок проведения.
Прежде чем чистить таблицы итогов, необходимо найти и исправить первоисточник проблемы — документы, сделавшие некорректные движения. Для этого воспользуемся консолью запросов 1С и выполним запрос к основной таблице движений проблемного регистра накопления:
ВЫБРАТЬ
Регистратор,
Период,
ДатаПлатежа
ИЗ
РегистрНакопления.РасчетыСПоставщиками КАК Расчеты
ГДЕ
Расчеты.Период = ДАТАВРЕМЯ(1, 1, 1)
ИЛИ Расчеты.ДатаПлатежа = ДАТАВРЕМЯ(1, 1, 1)
Если запрос вернул документы-регистраторы, их необходимо обработать:
Если на сильно замусоренной базе данных просто запустить штатный пересчет итогов через Конфигуратор, процесс гарантированно зависнет на несколько часов или аварийно завершится из-за нехватки оперативной памяти на сервере СУБД. Разберем два эффективных и безопасных способа очистки.
Самый простой и безопасный способ очистить физическую таблицу итогов в СУБД без использования сторонних SQL-скриптов — это временное отключение итогов для конкретного регистра. Пройдем по шагам этот процесс:
РегистрНакопления.РасчетыСПоставщиками).TRUNCATE или DROP для таблицы _AccumRgT). Миллионы фантомных записей мгновенно удаляются.Если база данных настолько огромна, что даже стандартные интерфейсы 1С работают со сбоями, администратор БД может очистить таблицу напрямую в SQL Server Management Studio (SSMS).
Важно: Все операции напрямую в СУБД должны выполняться строго на резервной копии базы данных и при отсутствии активных пользователей!
ПолучитьСтруктуруХраненияБазыДанных(). Допустим, имя таблицы итогов — _AccumRgT12345.
TRUNCATE TABLE _AccumRgT12345;
Чтобы исключить повторное появление подобных инцидентов, выполните профилактические настройки:
01.01.2000 для всех пользователей, включая администраторов. Это не позволит случайно записать или провести старые документы «нулевым» годом.Мы успешно локализовали проблему, очистили базу данных от лишнего информационного мусора и обеспечили стабильную, быструю работу механизмов расчета итогов!