Работа с большими массивами данных в 1С всегда требует особого подхода, особенно когда речь идет об удалении сотен тысяч записей. Стандартная процедура «Удаление помеченных объектов» зачастую не подходит для таких задач из-за отсутствия внятной индикации прогресса, низкой скорости работы и блокировок базы данных. Рассмотрим ситуацию, когда нам необходимо удалить порядка 500 000 элементов справочника, ссылки на которые не используются, и при этом сохранить работоспособность системы и видеть прогресс выполнения задачи.
Прежде чем приступать к удалению, проанализируем, почему стандартные методы могут давать сбой. Основная нагрузка при удалении ложится на индексы и транзакционный лог. Если попытаться удалить все 500 000 элементов в одной транзакции, файловая база данных (.1CD) может значительно вырасти в объеме в процессе операции, а оперативная память — переполниться. Если же удалять по одному элементу без использования транзакций, скорость будет крайне низкой из-за постоянного обращения к диску для фиксации каждой записи.
Разберем по шагам наиболее эффективные способы решения этой задачи, от простых программных циклов до продвинутых методов оптимизации.
Наиболее сбалансированный подход — удаление данных порциями (пакетами) в рамках отдельных транзакций. Это позволяет системе «дышать», сбрасывать кэш и дает возможность другим пользователям (если они есть) выполнять свои задачи. Проанализируем пример кода, который реализует такой подход:
// Пример удаления порциями по 1000 элементов
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ССЫЛКА
|ИЗ Справочник.ИмяВашегоСправочника
|ГДЕ Ссылка В (&МассивСсылокДляУдаления)"; // Здесь может быть ваш критерий отбора
Выборка = Запрос.Выполнить().Выбрать();
Счетчик = 0;
РазмерПорции = 1000;
Пока Выборка.Следующий() Цикл
Если Счетчик % РазмерПорции = 0 Тогда
Если Счетчик > 0 Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
НачатьТранзакцию();
КонецЕсли;
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.ОбменДанными.Загрузка = Истина; // Важнейший флаг для ускорения
Объект.Удалить();
Счетчик = Счетчик + 1;
// Здесь можно обновить индикатор прогресса
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Обратим внимание на свойство ОбменДанными.Загрузка = Истина. Установка этого флага отключает выполнение прикладных проверок в процедурах ПередЗаписью, ПриЗаписи и ПередУдалением. Поскольку автор темы указал, что ссылки не используются, это абсолютно безопасный способ радикально ускорить процесс.
В платформе 1С существует встроенный метод глобального контекста УдалитьОбъекты(). Он работает быстрее, чем удаление через объектную модель в цикле, так как платформа оптимизирует запрос к базе данных на уровне СУБД. Выясним, как применить его эффективно.
МассивСсылок = Новый Массив;
// Заполняем массив ссылками через запрос
// ...
Попытка
// Второй параметр Ложь означает, что мы НЕ проверяем ссылочную целостность
УдалитьОбъекты(МассивСсылок, Ложь);
Исключение
Сообщить("Ошибка при массовом удалении: " + ОписаниеОшибки());
КонецПопытки;
Важный нюанс: метод УдалитьОбъекты лучше всего использовать также порциями (например, по 5-10 тысяч ссылок), чтобы не вызвать переполнение памяти при формировании гигантского массива в оперативной памяти.
Рассмотрим более сложный, но профессиональный подход — адаптивный расчет количества элементов в транзакции. Суть метода заключается в том, что система замеряет время выполнения одной порции удаления. Если удаление произошло слишком быстро, размер следующей порции увеличивается. Если возникла ошибка блокировки или время превысило лимит — размер порции уменьшается. Это позволяет найти «золотую середину» производительности для конкретного оборудования и загруженности базы.
Чтобы избежать «фризов» интерфейса, о которых упоминал автор, правильно будет вынести процедуру удаления в фоновое задание. В управляемом приложении (8.3) для этого используется механизм БСП или штатные средства платформы. Проанализируем алгоритм:
ПодключитьОбработчикОжидания, который раз в 2-3 секунды считывает прогресс и обновляет полосу индикатора на экране пользователя.При использовании БСП (Библиотеки Стандартных Подсистем) рекомендуется обратить внимание на модуль ДлительныеОперации. Это позволит сделать интерфейс отзывчивым, и пользователь сможет даже закрыть форму, пока процесс идет на сервере.
Если нужно удалить 90% элементов из 500 000, иногда проще не удалять лишнее, а сохранить нужное. Рассмотрим шаги этого метода:
GUID, чтобы не нарушить ссылочную целостность в других документах (если они все же есть).Поскольку автор использует файловый вариант (без SQL), важно помнить о физической структуре файла .1CD. При удалении записей место в файле не освобождается автоматически — оно просто помечается как свободное для будущих записей. После удаления 500 000 элементов файл базы останется того же размера. Чтобы реально уменьшить размер файла на диске и перестроить индексы для ускорения работы, после завершения удаления необходимо выполнить «Сжатие таблиц» через конфигуратор (меню «Администрирование» — «Тестирование и исправление»).
Подведем итог: для решения задачи автора лучше всего подошел метод удаления порциями по 10 000 элементов с использованием ОбменДанными.Загрузка = Истина. Это позволило завершить операцию за одну ночь без критических зависаний системы. Если же требуется регулярное выполнение подобных задач, стоит реализовать механизм через фоновые задания для комфортной работы пользователей.