В процессе эксплуатации крупных информационных систем на базе 1С:Предприятие 8.3 пользователи и администраторы часто сталкиваются с проблемой крайне медленной работы стандартного механизма удаления помеченных объектов. Когда количество объектов исчисляется тысячами, а связи между ними запутаны, процесс может затягиваться на многие часы, блокируя работу пользователей. В такой ситуации часто помогает специализированное удаление помеченных на удаление объектов с предварительным отбором. В данной статье мы разберем по шагам, как оптимизировать этот процесс, проанализируем причины замедления и рассмотрим программные способы решения задачи.
Прежде чем переходить к активным действиям, давайте проанализируем ситуацию. Основная нагрузка при удалении ложится не на само удаление записи из базы данных, а на поиск ссылок на удаляемый объект. 1С должна гарантировать ссылочную целостность, поэтому перед удалением каждого элемента система проверяет всю базу данных на наличие упоминаний об этом объекте (в документах, регистрах, справочниках). Если в базе миллионы записей, поиск ссылок становится ресурсоемкой операцией.
Рассмотрим основные факторы, влияющие на скорость:
НайтиСсылки(). В ряде случаев перед удалением имеет смысл выполнить универсальное сжатие базы для очистки табличных частей закрытых периодов.В современных конфигурациях, построенных на базе Библиотеки стандартных подсистем (БСП), предусмотрен механизм фонового удаления. Давайте посмотрим на пример настройки этого режима. Использование фонового задания позволяет высвободить интерфейс пользователя и переложить нагрузку на сервер приложений.
Для активации этого режима выполним следующие действия:
Важный момент: фоновое удаление в типовых решениях часто работает итерационно, что позволяет избежать длительных транзакций, которые могут "подвесить" всю базу данных.
Если стандартные средства не справляются, мы как разработчики можем применить более агрессивные методы. Рассмотрим метод платформы УдалитьОбъекты(). В последних версиях платформы 8.3 этот метод был значительно оптимизирован.
Разберем программный код, который позволяет быстро удалить массив ссылок:
// Создаем массив объектов, которые нужно удалить
МассивОбъектов = Новый Массив;
// Допустим, мы уже выбрали ссылки, помеченные на удаление
МассивОбъектов.Добавить(СсылкаНаОбъект1);
МассивОбъектов.Добавить(СсылкаНаОбъект2);
// Второй параметр "Истина" означает проверку ссылочной целостности
// Третий параметр (МассивОтказов) вернет те объекты, которые не удалось удалить
МассивОтказов = Новый СписокЗначений;
УдалитьОбъекты(МассивОбъектов, Истина, МассивОтказов);
Если МассивОтказов.Количество() > 0 Тогда
Сообщить("Некоторые объекты не были удалены из-за наличия ссылок.");
КонецЕсли;
Почему этот метод быстрее? Проанализируем ситуацию: при передаче массива объектов платформа минимизирует количество обращений к таблицам метаданных. Вместо того чтобы сканировать регистр 100 раз для 100 разных ссылок, система может выполнить оптимизированный запрос сразу для всей группы.
Часто удаление не завершается, потому что один "популярный" объект (например, склад или организация) держит тысячи связей. Рассмотрим, как программно найти, что именно мешает удалению.
Воспользуемся методом НайтиПомеченныеНаУдаление() в сочетании с НайтиСсылки(). Разберем по шагам:
// Пример анализа связей
Помеченные = НайтиПомеченныеНаУдаление();
ТаблицаСсылок = НайтиСсылки(Помеченные);
Для Каждого СтрокаСсылки Из ТаблицаСсылок Цикл
// СтрокаСсылки.Данные - это объект, на который ссылаются
// СтрокаСсылки.Ссылка - это объект, который содержит ссылку
// Здесь можно реализовать логику автоматической очистки связей
КонецЦикла;
Рассмотрим подробнее: если вы видите, что на удаляемый документ ссылается запись регистра сведений ВерсииОбъектов, возможно, имеет смысл сначала очистить историю версий, чтобы ускорить основной процесс.
Внимание! Этот метод является экстремальным и должен применяться только опытными администраторами в исключительных случаях (например, при очистке временных данных или логов). Выясним причину, по которой это опасно: в базе могут остаться "битые" ссылки (Объект не найден), что приведет к ошибкам в отчетах и при проведении документов.
Если же такая ситуация уже произошла, вам понадобится универсальный комплекс очистки битых ссылок «Объект не найден» для диагностики и лечения базы. Также может быть полезен поиск и замена битых ссылок документов или, в случае проблем с регистрами, универсальное удаление движений по битым ссылкам.
Если вы уверены в своих действиях и понимаете риски, используйте метод Объект.Удалить() внутри транзакции:
НачатьТранзакцию();
Попытка
ОбъектДокумент = СсылкаНаУдаление.ПолучитьОбъект();
Если ОбъектДокумент <> Неопределено Тогда
ОбъектДокумент.Удалить(); // Прямое удаление без проверок ссылок в других местах
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("Ошибка удаления", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
Помимо манипуляций в конфигураторе 1С, проанализируем настройки сервера базы данных (SQL Server или PostgreSQL). Иногда проблема кроется в "раздутых" индексах или логах транзакций.
Simple на время операции.Мы рассмотрели несколько подходов к решению проблемы медленного удаления. Для повседневной работы лучше всего подходит использование стандартного фонового удаления БСП. Если же стоит задача разовой очистки огромной базы, эффективнее будет написать небольшую обработку, использующую групповой метод УдалитьОбъекты() и предварительный анализ "тяжелых" ссылок через НайтиСсылки().
Помните, что безопасность данных всегда важнее скорости. Всегда делайте резервную копию базы данных перед выполнением массовых операций удаления, особенно если используете методы без проверки ссылочной целостности.