Удаление большого объема данных в 1С — задача, с которой рано или поздно сталкивается любой разработчик при очистке базы от дублей или устаревшей номенклатуры. Когда счет идет на миллионы записей, стандартные методы удаления «в лоб» могут растянуться на недели. В этой статье мы подробно разберем эффективные стратегии ускорения удаления, проанализируем влияние транзакций на производительность СУБД и рассмотрим практические примеры кода.
Когда мы вызываем метод Удалить() для объекта в цикле без явного открытия транзакции, платформа 1С и СУБД выполняют огромный объем скрытой работы. Проанализируем, что происходит «под капотом»:
ПолучитьОбъект() платформа считывает все данные элемента в память, что создает лишнюю нагрузку на сеть и сервер приложений.ПередУдалением и ПриУдалении, а также все зарегистрированные подписки на события. Это может включать в себя дополнительные проверки ссылок и логику, которая замедляет процесс.Рассмотрим основной способ ускорения — группировку операций удаления в пакеты. Это позволяет СУБД записывать данные в журнал транзакций большими блоками, что существенно снижает нагрузку на диски. Выясним оптимальный размер пакета: как правило, это от 1 000 до 5 000 элементов. Слишком маленькие пакеты не дадут прироста, а слишком большие могут привести к эскалации блокировок (блокировке всей таблицы) и переполнению журнала транзакций.
Разберем пример кода для пакетного удаления:
НачатьТранзакцию();
Счетчик = 0;
РазмерПакета = 2000; // Оптимальное значение для средних серверов
Для Каждого Строка Из РезультатЗапроса Цикл
Счетчик = Счетчик + 1;
// Получаем объект напрямую по ссылке для удаления
Объект = Строка.Ссылка.ПолучитьОбъект();
Если Объект <> Неопределено Тогда
// Отключаем лишние проверки для ускорения
Объект.ОбменДанными.Загрузка = Истина;
Объект.Удалить();
КонецЕсли;
Если Счетчик % РазмерПакета = 0 Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
// Можно добавить вывод прогресса для мониторинга
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
При массовых операциях обязательно используйте свойство ОбменДанными.Загрузка = Истина. Это критически важный момент. Данный флаг сообщает платформе, что объект записывается (или удаляется) в режиме загрузки данных, а значит:
Это не только ускоряет процесс в 2–3 раза, но и позволяет избежать ошибок, связанных с бизнес-логикой, которая может запрещать удаление старых объектов.
Одной из самых долгих операций является проверка того, используется ли номенклатура в документах или регистрах. Вместо использования тяжелого метода НайтиПоСсылке(), проанализируем ситуацию и составим запрос к тем регистрам, где данные действительно могут быть.
Рассмотрим пример запроса, который находит дубли номенклатуры (по артикулу и наименованию), но исключает те, по которым были движения в регистре ТоварыНаСкладах:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Артикул В (
ВЫБРАТЬ Артикул
ИЗ Справочник.Номенклатура
СГРУППИРОВАТЬ ПО Артикул, Наименование
ИМЕЮЩИЕ КОЛИЧЕСТВО(Ссылка) > 1
)
И НЕ Номенклатура.Ссылка В (
ВЫБРАТЬ РАЗЛИЧНЫЕ Номенклатура
ИЗ РегистрНакопления.ТоварыНаСкладах
)
Такой подход позволяет одним махом отобрать «чистые» дубли, которые гарантированно можно удалять без нарушения ссылочной целостности.
Если ссылок на объекты гарантированно нет (например, это ошибочно загруженные прайсы), можно использовать прямое удаление средствами СУБД. Это самый быстрый способ, так как он обходит все уровни платформы 1С. Однако помните о рисках: 1С хранит данные справочников в нескольких таблицах (основная, табличные части, дополнительные реквизиты). Удаление только из основной таблицы приведет к появлению «битых» данных.
Пример структуры SQL-запроса для удаления (нужно подставить имена таблиц конкретной базы):
-- Будьте крайне осторожны! Сначала сделайте бэкап.
DELETE FROM _Reference123
WHERE _IDRRef IN (
SELECT ID FROM #TempTableForDeletion
)
Важный совет: после прямого удаления через SQL обязательно выполните Тестирование и исправление в конфигураторе (пункты «Проверка логической целостности» и «Очистка пустых ссылок»).
Если сервер обладает достаточными мощностями, процесс можно ускорить, запустив удаление в несколько потоков. Для этого:
Как показывает практика, запуск в 4–8 потоков может сократить время удаления в несколько раз, при условии, что дисковая подсистема сервера справляется с нагрузкой на журнал транзакций.
Подведем итоги нашего анализа. Для достижения максимальной скорости при удалении миллионов записей придерживайтесь следующего алгоритма:
ОбменДанными.Загрузка = Истина.Проанализировав результаты тестов, можно утверждать: грамотное использование транзакций и отказ от лишних проверок позволяют удалять более 1 миллиона позиций за несколько часов, что является отличным результатом для платформы 1С.