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

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

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

В старых версиях платформы (например, в легендарной 1С 7.7) эта задача решалась тривиально — физическим удалением файлов таблиц .dbf с последующей реиндексацией информационной базы. В современных реалиях работы с управляемыми формами, клиент-серверной архитектурой и сложными бизнес-приложениями этот подход не применим. В этой статье мы подробно разберем, как максимально быстро очистить базу данных от ненужных объектов программными и СУБД-методами, не нарушая работоспособность системы.

Способ 1. Непосредственное удаление через Удалить() с отключением бизнес-логики

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

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

Проанализируем пример кода, реализующий этот подход:


Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
    СпрОбъект = Выборка.ПолучитьОбъект();
    СпрОбъект.ОбменДанными.Загрузка = Истина;
    СпрОбъект.Удалить();
КонецЦикла;

Установка свойства ОбменДанными.Загрузка = Истина сообщает платформе 1С, что операция выполняется в режиме обмена (синхронизации). Платформа при этом автоматически отключает большинство прикладных проверок и обработчиков событий, что ускоряет процедуру удаления в несколько раз. Важно отметить, что после выполнения подобных операций разработчику обязательно необходимо запустить утилиту Тестирование и исправление (ТИИ) для проверки логической целостности базы данных, так как в системе могут остаться "битые" ссылки на удаленные элементы.

Способ 2. Групповое пакетное удаление через УдалитьОбъекты()

Главный недостаток Способа 1 заключается в том, что в цикле происходит вызов тяжелого метода ПолучитьОбъект(). Этот метод инициализирует объект в оперативной памяти сервера приложений, считывает все его реквизиты, табличные части и метаданные. При удалении миллионов записей этот процесс создает колоссальную нагрузку на CPU и память.

Для оптимизации процесса мы можем использовать встроенный глобальный метод контекста УдалитьОбъекты(). Этот метод позволяет выполнять пакетное удаление массива ссылок за один шаг.

Рассмотрим структуру вызова данного метода:


// Создаем массив ссылок для удаления
МассивУдаления = Новый Массив;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    МассивУдаления.Добавить(Выборка.Ссылка);
КонецЦикла;

// Удаляем объекты пакетом без проверки ссылочной целостности
УдалитьОбъекты(МассивУдаления, Ложь);

Разберем параметры метода УдалитьОбъекты(СписокОбъектов, ПроверятьСсылочнуюЦелостность). Передавая во второй параметр значение Ложь, мы полностью отключаем контроль ссылочной целостности со стороны платформы. Платформа формирует оптимизированный пакетный запрос к СУБД, что работает в десятки раз быстрее, чем удаление каждого объекта по отдельности через цикл с получением объектов в памяти.

Способ 3. Оптимизация работы с транзакциями

При выполнении любых массовых операций изменения данных в 1С критически важным фактором производительности является правильное управление транзакциями. По умолчанию СУБД оборачивает каждую отдельную операцию удаления в собственную транзакцию. Это приводит к тому, что на каждый удаленный объект жесткий диск сервера СУБД выполняет физическую операцию записи (коммита) в лог транзакций (например, файл .ldf в MS SQL Server).

Чтобы ускорить этот процесс, нам необходимо группировать операции удаления в более крупные транзакции. Выясним на примере, как реализовать порционное удаление в транзакциях:


МассивДляПорции = Новый Массив;
Порция = 1000; // Оптимальный размер порции данных

Для Каждого ТекущаяСсылка Из МассивОбъектов Цикл
    МассивДляПорции.Добавить(ТекущаяСсылка);
    
    Если МассивДляПорции.Количество() >= Порция Тогда
        НачатьТранзакцию();
        Попытка
            УдалитьОбъекты(МассивДляПорции, Ложь);
            ЗафиксироватьТранзакцию();
        Исключение
            ОтменитьТранзакцию();
            ВызватьИсключение; // Или залогировать ошибку
        КонецПопытки;
        МассивДляПорции.Очистить();
    КонецЕсли;
КонецЦикла;

// Не забываем удалить остаток
Если МассивДляПорции.Количество() > 0 Тогда
    НачатьТранзакцию();
    Попытка
        УдалитьОбъекты(МассивДляПорции, Ложь);
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
    КонецПопытки;
КонецЕсли;

Опытным путем установлено, что оптимальный размер порции для одной транзакции колеблется в пределах от 1 000 до 5 000 объектов. Слишком маленький размер не даст прироста скорости, а слишком большой может привести к эскалации блокировок таблиц в СУБД и нехватке оперативной памяти.

Способ 4. Отключение Журнала регистрации и дополнительных механизмов БСП

При массовом удалении платформа 1С по умолчанию фиксирует каждое событие удаления в Журнале регистрации (ЖР). Запись сотен тысяч событий в ЖР создает серьезную дисковую очередь. Если перед нами стоит задача экстренной очистки базы, мы можем временно отключить Журнал регистрации в конфигураторе (установив режим "Не регистрировать") или сократить уровень детализации до регистрации только ошибок.

Кроме того, в современных типовых конфигурациях, построенных на БСП (Библиотеке стандартных подсистем), при удалении объектов запускаются фоновые процессы пересчета ключей доступа RLS (разграничения прав доступа на уровне записей). Это может парализовать работу базы данных.

Для решения этой проблемы перед запуском удаления рекомендуется программно приостановить обновление ключей доступа, используя методы БСП:


// Приостанавливаем обновление ключей доступа
УправлениеДоступомСлужебный.ПриостановитьОбновлениеКлючейДоступа();

// ... Выполняем массовое удаление данных ...

// Возобновляем обновление и запускаем фоновый пересчет
УправлениеДоступомСлужебный.ВозобновитьОбновлениеКлючейДоступа();

Способ 5. Предварительная очистка движений документов

Если мы удаляем проведенные документы, то СУБД тратит основную часть времени не на удаление самого документа, а на очистку его движений по связанным регистрам накопления, сведений и бухгалтерии. Платформа 1С делает это автоматически, последовательно очищая таблицы движений. При обслуживании крупных баз 1С:ERP параллельно очистить старые записи регистров и пометить документы на удаление в несколько потоков можно с помощью обработки для многопоточной свёртки 1С:ERP.

Чтобы радикально ускорить процесс, мы рекомендуем предварительно очистить движения удаляемых документов "пустыми наборами записей". Посмотрим на пример кода очистки движений:


Для Каждого ДокСсылка Из МассивДокументов Цикл
    // Очищаем движения по конкретному регистру
    Набор = РегистрыНакопления.Продажи.СоздатьНаборЗаписей();
    Набор.Отбор.Регистратор.Установить(ДокСсылка);
    Набор.Записать(); // Запись пустого набора очищает движения
КонецЦикла;

Только после того как все движения документов будут очищены, мы можем вызывать метод группового удаления самих документов. Это убережет СУБД от избыточных блокировок и ускорит процесс в разы. Дополнительно на время проведения массовой очистки рекомендуется отключить использование итогов по задействованным регистрам с помощью метода УстановитьИспользованиеИтогов(Ложь) с последующим их включением и полным пересчетом.

Способ 6. Использование готовых инструментов администрирования

Если вы не хотите писать собственный программный код, вы можете воспользоваться проверенными временем стандартными обработками от фирмы 1С. Для обычных форм отлично подходит обработка Универсальные_подбор_и_обработка_объектов, а для управляемых форм — встроенная обработка БСП Групповое изменение реквизитов (или аналогичная внешняя обработка подбора и обработки). Для этой задачи также подойдёт готовая внешняя обработка для удаления справочников и документов в 1С 8.3 без изменения конфигурации.

Для быстрой очистки в этих обработках необходимо выполнить следующие настройки:

  1. Выбрать интересующий нас тип объектов (справочник или документ).
  2. Настроить отборы, чтобы в выборку попали только целевые элементы.
  3. В параметрах обработки обязательно включить флаг Режим загрузки данных (ОбменДанными.Загрузка = Истина). В некоторых версиях обработок этот режим находится в дополнительных настройках под правами администратора.
  4. Выбрать действие "Удалить" (не путать с "Пометить на удаление").

Благодаря включенному режиму обмена данными, обработка произведет непосредственное удаление выбранного массива объектов на максимальной скорости, доступной платформенным механизмам.

Способ 7. Прямое удаление через СУБД (Для SQL-баз)

Самым быстрым из всех возможных вариантов физического удаления данных является использование прямых SQL-запросов к СУБД (MS SQL Server, PostgreSQL и др.). Операция DELETE FROM или TRUNCATE TABLE на уровне СУБД выполняется практически мгновенно.

Важное предупреждение: Использование этого метода нарушает условия лицензионного соглашения фирмы 1С, которое запрещает напрямую изменять структуру данных и записи таблиц SQL в обход сервера приложений 1С. Кроме того, этот метод требует глубокого понимания внутренней структуры таблиц вашей базы данных (так как таблицы и поля в СУБД имеют неявные системные имена, например, _Reference54 или _Document112).

Если вы все же решились прибегнуть к этому методу на свой страх и риск (например, на тестовой копии базы), разберем базовые SQL-команды:

  1. Команда DELETE FROM _Reference54 — удаляет все строки из таблицы справочника. Этот метод записывает лог транзакций SQL, поэтому на терабайтных базах может работать медленнее, чем ожидается.
  2. Команда TRUNCATE TABLE _Reference54 — полностью очищает таблицу мгновенно, не записывая подробный лог транзакций для каждой строки. Это самый быстрый способ очистить таблицу "под ноль".
  3. Метод "перелива" (когда нужно оставить лишь малую часть данных):
    • Создаем временную таблицу в СУБД и копируем туда те 10-20% записей из оригинальной таблицы 1С, которые **необходимо сохранить**.
    • Выполняем быструю команду TRUNCATE TABLE для оригинальной таблицы 1С.
    • Переносим сохраненные записи из временной таблицы обратно в оригинальную таблицу 1С.

Помните, что после любых прямых манипуляций на уровне СУБД база данных 1С теряет согласованность кэша. Вам потребуется перезапустить службу сервера 1С:Предприятие и обязательно выполнить полную проверку базы через механизм Тестирования и исправления конфигуратора с включенными опциями "Реорганизация данных" и "Очистка неработающих ссылок". Если требуется регулярно проводить обслуживание и проверять целостность нескольких баз в автоматическом режиме, запускать эти процедуры удобно с помощью программы для автоматического тестирования баз 1С.

← На главную