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