Работа с большими массивами данных в 1С часто сопряжена с проблемами производительности. Удаление даже 40 000 записей может затянуться на десятки минут, если использовать стандартные методы «в лоб». В этой статье мы подробно разберем, как оптимизировать процесс удаления, какие инструменты предоставляет платформа и как избежать блокировок системы при выполнении таких регламентных задач.
Прежде чем переходить к решениям, выясним причину, почему обычный цикл с вызовом Объект.Удалить() работает так медленно. Проблема заключается в том, что при каждом вызове метода платформа выполняет целый ряд действий:
ПередУдалением и ПриУдалении.Рассмотрим способы, которые позволяют обойти эти ограничения.
Это самый сбалансированный способ, который остается в рамках идеологии 1С, но работает в разы быстрее стандартного удаления. Секрет заключается в использовании специального объекта УдалениеОбъекта и флага ОбменДанными.Загрузка = Истина.
Проанализируем пример кода, который позволяет ускорить процесс в 5-10 раз:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Удаление = Новый УдалениеОбъекта(Выборка.Ссылка);
Удаление.ОбменДанными.Загрузка = Истина;
Удаление.Записать();
КонецЦикла;
Разберем по шагам, что здесь происходит. Во-первых, мы не создаем объект справочника (не вызываем ПолучитьОбъект()), что экономит время на чтении данных. Во-вторых, установка свойства Загрузка = Истина отключает все проверки и обработчики событий (как в модуле объекта, так и в подписках). Это критически важный момент для скорости.
При удалении 40к записей SQL-сервер может применить эскалацию блокировок, закрыв доступ к таблице для всех пользователей. Чтобы этого избежать, мы рекомендуем удалять данные порциями (пакетами) в рамках отдельных транзакций. Проанализируем ситуацию: если удалять по одной записи — это медленно из-за накладных расходов на транзакции. Если удалять всё одной транзакцией — это опасно блокировками. Оптимальный размер порции — от 1000 до 5000 записей.
Посмотрим на пример реализации пакетного удаления:
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.ИмяСправочника");
Результат = Запрос.Выполнить().Выгрузить();
ВсегоЗаписей = Результат.Количество();
РазмерПорции = 1000;
Счетчик = 0;
Пока Счетчик < ВсегоЗаписей Цикл
НачатьТранзакцию();
Для Итератор = 1 По РазмерПорции Цикл
Если Счетчик >= ВсегоЗаписей Тогда Прервать; КонецЕсли;
ТекСсылка = Результат[Счетчик].Ссылка;
Удаление = Новый УдалениеОбъекта(ТекСсылка);
Удаление.ОбменДанными.Загрузка = Истина;
Удаление.Записать();
Счетчик = Счетчик + 1;
КонецЦикла;
ЗафиксироватьТранзакцию();
КонецЦикла;
Важно: Такой подход позволяет другим пользователям работать с базой в перерывах между транзакциями и предотвращает бесконтрольный рост файла лога транзакций (LDF).
В современных версиях платформы появился объект УдалениеДанных, предназначенный специально для массовых операций. Он работает максимально близко к уровню СУБД. Рассмотрим пример его использования:
МассивСсылок = Новый Массив; // Заполняем массив ссылками для удаления
Удаление = УдалениеДанных.Создать();
Удаление.Параметры.ВключатьПроверкуСсылочнойЦелостности = Ложь;
Удаление.Выполнить(МассивСсылок);
Этот метод оптимизирован внутри самой платформы и является наиболее современным решением для задач массовой очистки данных.
Если ваша база работает в клиент-серверном варианте и вы обладаете правами администратора СУБД, можно использовать команду TRUNCATE TABLE. Это самый быстрый способ во вселенной (занимает миллисекунды), так как он просто очищает страницы данных таблицы, не записывая удаление каждой строки в лог.
Однако здесь есть огромные риски, которые мы должны учитывать:
_ReferenceX, а табличные части — _ReferenceX_VT_Y. Команда TRUNCATE по основной таблице оставит «мусор» в таблицах ТЧ.Поэтому метод через SQL (например, через ADODB.Connection) стоит использовать только в исключительных случаях, когда вы точно знаете, что ссылок на объект нет и структура таблиц вам полностью понятна.
Для разовых задач очистки удобно использовать консоли из состава «Инструментов разработчика» (автор С. Старых). В них реализован функционал «Очистка таблиц СУБД», который автоматически находит все связанные таблицы справочника и выполняет их быструю очистку на уровне SQL, сохраняя при этом корректность структуры данных с точки зрения СУБД.
Выясним, что нужно сделать после того, как 40 000 записей были успешно удалены. Массовое удаление создает «дыры» в индексах и таблицах, что может замедлить последующую работу.
UPDATE STATISTICS.Подводя итог, для большинства задач оптимальным выбором будет Способ 1 с использованием УдалениеОбъекта и Загрузка = Истина. Это безопасно, быстро и не требует глубоких знаний устройства SQL-таблиц.