Каждый администратор и разработчик 1С рано или поздно сталкивается с проблемой лавинообразного роста служебных таблиц. В типовой конфигурации «1С:Бухгалтерия предприятия» (БП) одним из главных виновников этого процесса часто становится регистр сведений ИсторияОбменаДанными. В файловом варианте работы базы данных разрастание этого регистра до объема более 3 Гб превращает любую попытку стандартной очистки в техническую проблему: система аварийно завершает работу с ошибкой «Недостаточно памяти».
В этой статье мы подробно разберем, почему возникает эта ошибка, и рассмотрим проверенные практические методы полной или частичной очистки регистра сведений, которые позволят вернуть базу данных в рабочее состояние без потери стабильности конфигурации.
Прежде чем приступать к активным действиям, давайте проанализируем ситуацию. При попытке выполнить метод Записать() для пустого набора записей без установленного отбора на огромной таблице платформа 1С пытается прочитать и заблокировать всю физическую таблицу в оперативной памяти.
Если вы работаете под управлением 32-битного клиента или конфигуратора 1С:Предприятие, адресное пространство процесса жестко ограничено 2 Гб (в редких случаях — до 3-4 Гб при использовании специальных ключей операционной системы). Когда объем обрабатываемого индекса и самих данных превышает этот лимит, операционная система отказывает платформе в выделении дополнительной памяти, что приводит к гарантированному вылету приложения.
Ниже мы подробно изучим несколько эффективных способов решения этой проблемы, начиная с простых конфигурационных манипуляций и заканчивая тонкой оптимизацией программного кода.
Если перед вами стоит задача **полной** очистки регистра сведений (без сохранения накопленных записей), самым быстрым решением для файловой базы будет его временное исключение из структуры метаданных. Этот способ хорош тем, что физическое удаление таблицы происходит на уровне движка СУБД базы данных чрезвычайно быстро.
Рассмотрим этот алгоритм по шагам:
config.cf.ИсторияОбменаДанными) в дереве метаданных, нажмите клавишу Del и удалите его из конфигурации.F7 (или выбрав Конфигурация -> Обновить конфигурацию базы данных). Подтвердите удаление таблицы. На этом этапе платформа полностью уничтожит физическую таблицу регистра на диске, освободив оперативную память.config.cf.ИсторияОбменаДанными.F7. Платформа создаст новую, абсолютно чистую структуру таблиц для этого регистра.После выполнения этой процедуры структура регистра будет полностью пустой, однако физический размер файла базы данных .1CD не уменьшится автоматически. Для физического сжатия базы обязательно выполните операцию сжатия таблиц, которую мы подробно опишем далее.
Существует еще один изящный способ очистить независимый регистр сведений без его полного удаления из метаданных. Мы можем использовать особенность реструктуризации таблиц платформой 1С при изменении подчиненности объекта.
Разберем, как устроен этот трюк:
Независимый.F7). При реструктуризации платформа обнаружит, что у всех существующих записей регистра отсутствует обязательное заполненное поле регистратора. Так как привязать старые записи к регистраторам автоматически невозможно, система просто полностью очистит физическую таблицу данных.Независимый.F7). На выходе вы получите чистый независимый регистр сведений.Бывают ситуации, когда деструктивные методы работы с конфигурацией не подходят (например, конфигурация находится на жесткой поддержке без возможности изменений, или вам необходимо удалить только часть данных, удовлетворяющих определенным условиям). В таком случае очистку нужно выполнять программным кодом, но делать это порционно.
Поскольку стандартный набор записей независимого регистра сведений требует жесткого отбора по равенству измерений, мы не можем просто сказать системе «удали записи, где дата меньше определенной». Нам придется использовать обход по ключевым полям.
Рассмотрим пример кода для порционного удаления данных с группировкой операций в транзакции. Этот подход защитит оперативную память от переполнения:
ВыборкаУникальных = Новый Запрос;
ВыборкаУникальных.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 50000
| ИсторияОбменаДанными.УзелОбмена КАК УзелОбмена,
| ИсторияОбменаДанными.Период КАК Период
|ИЗ
| РегистрСведений.ИсторияОбменаДанными КАК ИсторияОбменаДанными";
ТаблицаКлючей = ВыборкаУникальных.Выполнить().Выгрузить();
Пока ТаблицаКлючей.Количество() > 0 Цикл
НачатьТранзакцию();
Для Каждого СтрокаКлюча Из ТаблицаКлючей Цикл
НаборЗаписей = РегистрыСведений.ИсторияОбменаДаннымиСоздатьНаборЗаписей();
НаборЗаписей.Отбор.УзелОбмена.Установить(СтрокаКлюча.УзелОбмена);
НаборЗаписей.Отбор.Период.Установить(СтрокаКлюча.Период);
// Записываем пустой набор, что приводит к удалению записи
НаборЗаписей.Записать(Истина);
КонецЦикла;
ЗафиксироватьТранзакцию();
// Получаем следующую порцию данных для удаления
ТаблицаКлючей = ВыборкаУникальных.Выполнить().Выгрузить();
КонецЦикла;
Проанализируем этот код: конструкция ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 50000 позволяет нам выбирать данные небольшими частями. Использование транзакции (НачатьТранзакцию() и ЗафиксироватьТранзакцию()) значительно ускоряет запись на диск в файловом режиме работы, поскольку изменения сбрасываются пакетом, а не для каждой отдельной строки.
Если у вас есть возможность запустить Конфигуратор или клиентское приложение на 64-разрядной версии платформы 1С:Предприятие (в современных релизах платформы начиная с 8.3.9 64-битные клиенты для Windows поставляются штатно), проблема дефицита адресуемой памяти решится сама собой.
Запуск под 64-битным процессом позволяет системе использовать всю физически доступную оперативную память компьютера (например, 8, 16 или 32 Гб вместо жесткого лимита в 2 Гб). В этом случае даже стандартное удаление набора записей без отборов или полное Тестирование и Исправление (ТиИ) отработает корректно и без аварийных завершений.
Удаление записей из таблиц файловой базы 1С (как программное, так и конфигурационное) фактически помечает страницы в файле .1CD как свободные, но сам файл на физическом диске компьютера не уменьшается в размерах. Чтобы уменьшить размер базы до реального объема оставшихся данных, выполните одну из следующих процедур:
В случае, если база данных повреждена или ТиИ завершается с ошибками памяти, воспользуйтесь стандартным механизмом упаковки через промежуточный файл выгрузки:
.dt.Этот процесс полностью пересоздает внутреннюю структуру файла .1CD с нуля, эффективно избавляясь от «мусорных» данных и уменьшая физический размер базы до минимально возможного.