Свёртка крупных информационных баз конфигурации 1С:Управление производственным предприятием (УПП 1.3) стандартной обработкой СверткаБазы.epf нередко приводит к падению платформы с системной ошибкой «Недостаточно памяти». Ситуация усугубляется, если используется 32-разрядный клиент или 32-разрядный сервер 1С:Предприятие (rphost), где максимальное адресное пространство одного процесса физически ограничено 3,5–4 ГБ независимо от общего объёма оперативной памяти на физическом сервере.
Особенно часто с этой задачей сталкиваются при подготовке копии базы для налоговых аудиторов или проверяющих органов, когда требуется оставить данные за последние 2–3 года и исключить первичные документы за предыдущие 5–7 лет. Проанализируем ключевые причины возникновения ошибки и рассмотрим надежные пошаговые методы подготовки базы без сбоев платформы.
Выясним причину сбоя. Типовая обработка свёртки проектировалась без расчёта на многолетние базы объёмом в десятки и сотни гигабайт. При выполнении стандартного сценария платформа перегружает оперативную память по следующим причинам:
ПередЗаписью, ПриЗаписи), порождая паразитные вычисления.Разберем рабочий сценарий, который позволяет обойти ошибку переполнения памяти без модификации системных библиотек:
КорректировкаЗаписейРегистров или специализированные документы ввода остатков) на нужную дату среза, отключив шаг удаления первичных документов.23:59:59 дня, предшествующего началу проверяемого периода.Для ускорения записи документов остатков и отключения фоновых проверок обязательно используем признак ОбменДанными.Загрузка = Истина. Посмотрим на пример кода формирования движений:
ДокументОстатков = Документы.КорректировкаЗаписейРегистров.СоздатьДокумент();
ДокументОстатков.Дата = ДатаСреза;
ДокументОстатков.Комментарий = "Ввод начальных остатков под проверку";
ДокументОстатков.ОбменДанными.Загрузка = Истина;
ДокументОстатков.Записать();
В конфигурации 1С:УПП 1.3 полное физическое удаление документов за 5–7 лет практически невозможно без повреждения аналитики: документы прошлых лет остаются в закрытых субконто, взаиморасчетах по договорам, регистрах НДС и партионного учёта. Попытка принудительно удалить их через ссылочный контроль вызывает лавину ошибок.
Оптимальный путь для проверяющих — оставить так называемые «оболочки» документов, полностью очистив их финансовую начинку:
Проведен = Ложь).Такой подход не ломает ссылочную целостность базы, не требует построения огромных таблиц зависимостей в ОЗУ и отрабатывает в разы быстрее полного удаления. Разберем пример процедуры для пакетной очистки движений:
Выборка = Документы.РеализацияТоваровУслуг.Выбрать(Дата("20100101"), ДатаСреза);
Пока Выборка.Следующий() Цикл
ОбъектДок = Выборка.ПолучитьОбъект();
ОбъектДок.ОбменДанными.Загрузка = Истина;
// Очищаем движения по регистрам
Для Каждого Движение Из ОбъектДок.Движения Цикл
Движение.Прочитать();
Если Движение.Количество() > 0 Тогда
Движение.Очистить();
Движение.ОбменДанными.Загрузка = Истина;
Движение.Записать();
КонецЕсли;
КонецЦикла;
// Снимаем признак проведения и очищаем табличную часть
ОбъектДок.Проведен = Ложь;
ОбъектДок.Товары.Очистить();
ОбъектДок.Услуги.Очистить();
ОбъектДок.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;
Если цель заключается именно в физическом удалении объектов из базы (чтобы проверяющие не видели даже заголовков документов), типовую обработку применять нельзя. Выполним порционное удаление напрямую через платформенный метод УдалитьОбъекты() с отключенным флагом проверки ссылок.
Рассмотрим правила, которые предотвратят падение процесса по памяти:
ЗафиксироватьТранзакцию(), сбрасывая кэш.Посмотрим на пример пакетного удаления ссылок:
МассивДляУдаления = Новый Массив;
Выборка = Документы.ПоступлениеТоваровУслуг.Выбрать(Дата("20100101"), ДатаСреза);
Пока Выборка.Следующий() Цикл
МассивДляУдаления.Добавить(Выборка.Ссылка);
Если МассивДляУдаления.Количество() >= 1000 Тогда
НачатьТранзакцию();
// Второй параметр Ложь отключает ресурсоемкий поиск ссылок
УдалитьОбъекты(МассивДляУдаления, Ложь);
ЗафиксироватьТранзакцию();
МассивДляУдаления.Очистить();
КонецЕсли;
КонецЦикла;
Если МассивДляУдаления.Количество() > 0 Тогда
НачатьТранзакцию();
УдалитьОбъекты(МассивДляУдаления, Ложь);
ЗафиксироватьТранзакцию();
МассивДляУдаления.Очистить();
КонецЕсли;
Перед проведением массовых операций очистки или формирования остатков в УПП необходимо отключить поддержание итогов по регистрам накопления и регистрам бухгалтерии. Это существенно экономит память сервера:
// Отключение итогов перед процедурой
РегистрыНакопления.ВзаиморасчетыСКонтрагентами.УстановитьИспользованиеИтогов(Ложь);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);
// ... выполнение операций ввода остатков и очистки ...
// Включение итогов после завершения
РегистрыНакопления.ВзаиморасчетыСКонтрагентами.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();
После завершения процедур в копии базы обязательно запустите операцию «Тестирование и исправление» в Конфигураторе с обязательной установкой флагов «Реструктуризация таблиц информационной базы» и «Пересчет итогов», а также выполните сжатие базы средствами СУБД (Shrink Database в MS SQL Server), чтобы освободить физическое дисковое пространство.