Как правильно и быстро удалить большое количество элементов справочника в 1С

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

Работа с большими массивами данных в 1С всегда требует особого подхода, особенно когда речь идет об удалении сотен тысяч записей. Стандартная процедура «Удаление помеченных объектов» зачастую не подходит для таких задач из-за отсутствия внятной индикации прогресса, низкой скорости работы и блокировок базы данных. Рассмотрим ситуацию, когда нам необходимо удалить порядка 500 000 элементов справочника, ссылки на которые не используются, и при этом сохранить работоспособность системы и видеть прогресс выполнения задачи.

Анализ проблемы и выбор стратегии

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

Разберем по шагам наиболее эффективные способы решения этой задачи, от простых программных циклов до продвинутых методов оптимизации.

Способ 1. Пакетное удаление с использованием транзакций

Наиболее сбалансированный подход — удаление данных порциями (пакетами) в рамках отдельных транзакций. Это позволяет системе «дышать», сбрасывать кэш и дает возможность другим пользователям (если они есть) выполнять свои задачи. Проанализируем пример кода, который реализует такой подход:


// Пример удаления порциями по 1000 элементов
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ССЫЛКА 
    |ИЗ Справочник.ИмяВашегоСправочника 
    |ГДЕ Ссылка В (&МассивСсылокДляУдаления)"; // Здесь может быть ваш критерий отбора

Выборка = Запрос.Выполнить().Выбрать();
Счетчик = 0;
РазмерПорции = 1000;

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

Если ТранзакцияАктивна() Тогда
    ЗафиксироватьТранзакцию();
КонецЕсли;

Обратим внимание на свойство ОбменДанными.Загрузка = Истина. Установка этого флага отключает выполнение прикладных проверок в процедурах ПередЗаписью, ПриЗаписи и ПередУдалением. Поскольку автор темы указал, что ссылки не используются, это абсолютно безопасный способ радикально ускорить процесс.

Способ 2. Использование метода УдалитьОбъекты

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


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

Важный нюанс: метод УдалитьОбъекты лучше всего использовать также порциями (например, по 5-10 тысяч ссылок), чтобы не вызвать переполнение памяти при формировании гигантского массива в оперативной памяти.

Способ 3. Адаптивный расчет размера транзакции (Метод дихотомии)

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

Способ 4. Фоновые задания и индикация прогресса

Чтобы избежать «фризов» интерфейса, о которых упоминал автор, правильно будет вынести процедуру удаления в фоновое задание. В управляемом приложении (8.3) для этого используется механизм БСП или штатные средства платформы. Проанализируем алгоритм:

  1. Создаем серверную процедуру удаления, которая будет работать в фоне.
  2. В этой процедуре через каждые N элементов записываем текущий процент выполнения в ВременноеХранилище или специальный регистр сведений.
  3. На форме создаем ПодключитьОбработчикОжидания, который раз в 2-3 секунды считывает прогресс и обновляет полосу индикатора на экране пользователя.

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

Способ 5. Радикальный метод (Пересоздание справочника)

Если нужно удалить 90% элементов из 500 000, иногда проще не удалять лишнее, а сохранить нужное. Рассмотрим шаги этого метода:

  1. Выгружаем нужные элементы (те 5-10%, которые должны остаться) во внешнюю обработку или XML-файл, обязательно сохраняя их УИД (Уникальный идентификатор).
  2. В конфигураторе полностью очищаем справочник (или удаляем его и создаем заново с теми же реквизитами).
  3. Выполняем реструктуризацию базы данных.
  4. Загружаем сохраненные элементы обратно с их исходными GUID, чтобы не нарушить ссылочную целостность в других документах (если они все же есть).

Особенности файловой базы данных

Поскольку автор использует файловый вариант (без SQL), важно помнить о физической структуре файла .1CD. При удалении записей место в файле не освобождается автоматически — оно просто помечается как свободное для будущих записей. После удаления 500 000 элементов файл базы останется того же размера. Чтобы реально уменьшить размер файла на диске и перестроить индексы для ускорения работы, после завершения удаления необходимо выполнить «Сжатие таблиц» через конфигуратор (меню «Администрирование» — «Тестирование и исправление»).

Подведем итог: для решения задачи автора лучше всего подошел метод удаления порциями по 10 000 элементов с использованием ОбменДанными.Загрузка = Истина. Это позволило завершить операцию за одну ночь без критических зависаний системы. Если же требуется регулярное выполнение подобных задач, стоит реализовать механизм через фоновые задания для комфортной работы пользователей.

← На главную