Как ускорить удаление миллионов элементов справочника в 1С: транзакции, SQL и оптимизация

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

Удаление большого объема данных в 1С — задача, с которой рано или поздно сталкивается любой разработчик при очистке базы от дублей или устаревшей номенклатуры. Когда счет идет на миллионы записей, стандартные методы удаления «в лоб» могут растянуться на недели. В этой статье мы подробно разберем эффективные стратегии ускорения удаления, проанализируем влияние транзакций на производительность СУБД и рассмотрим практические примеры кода.

Почему удаление по одному элементу работает медленно?

Когда мы вызываем метод Удалить() для объекта в цикле без явного открытия транзакции, платформа 1С и СУБД выполняют огромный объем скрытой работы. Проанализируем, что происходит «под капотом»:

  1. Неявные транзакции: СУБД создает отдельную транзакцию на каждую запись. Это заставляет дисковую подсистему подтверждать запись в журнал логов (LDF) для каждой операции удаления отдельно.
  2. Объектная модель: При использовании метода ПолучитьОбъект() платформа считывает все данные элемента в память, что создает лишнюю нагрузку на сеть и сервер приложений.
  3. Обработчики событий: Вызываются процедуры ПередУдалением и ПриУдалении, а также все зарегистрированные подписки на события. Это может включать в себя дополнительные проверки ссылок и логику, которая замедляет процесс.
  4. Регистрация изменений: Если справочник участвует в обмене данными, платформа записывает информацию об удалении в таблицы изменений планов обмена.

Метод 1: Использование пакетных транзакций

Рассмотрим основной способ ускорения — группировку операций удаления в пакеты. Это позволяет СУБД записывать данные в журнал транзакций большими блоками, что существенно снижает нагрузку на диски. Выясним оптимальный размер пакета: как правило, это от 1 000 до 5 000 элементов. Слишком маленькие пакеты не дадут прироста, а слишком большие могут привести к эскалации блокировок (блокировке всей таблицы) и переполнению журнала транзакций.

Разберем пример кода для пакетного удаления:


НачатьТранзакцию();
Счетчик = 0;
РазмерПакета = 2000; // Оптимальное значение для средних серверов

Для Каждого Строка Из РезультатЗапроса Цикл
    Счетчик = Счетчик + 1;
    
    // Получаем объект напрямую по ссылке для удаления
    Объект = Строка.Ссылка.ПолучитьОбъект();
    Если Объект <> Неопределено Тогда
        // Отключаем лишние проверки для ускорения
        Объект.ОбменДанными.Загрузка = Истина;
        Объект.Удалить();
    КонецЕсли;
    
    Если Счетчик % РазмерПакета = 0 Тогда
        ЗафиксироватьТранзакцию();
        НачатьТранзакцию();
        // Можно добавить вывод прогресса для мониторинга
    КонецЕсли;
КонецЦикла;

Если ТранзакцияАктивна() Тогда
    ЗафиксироватьТранзакцию();
КонецЕсли;

Метод 2: Режим «ОбменДанными.Загрузка = Истина»

При массовых операциях обязательно используйте свойство ОбменДанными.Загрузка = Истина. Это критически важный момент. Данный флаг сообщает платформе, что объект записывается (или удаляется) в режиме загрузки данных, а значит:

Это не только ускоряет процесс в 2–3 раза, но и позволяет избежать ошибок, связанных с бизнес-логикой, которая может запрещать удаление старых объектов.

Метод 3: Оптимизация поиска ссылок и дублей

Одной из самых долгих операций является проверка того, используется ли номенклатура в документах или регистрах. Вместо использования тяжелого метода НайтиПоСсылке(), проанализируем ситуацию и составим запрос к тем регистрам, где данные действительно могут быть.

Рассмотрим пример запроса, который находит дубли номенклатуры (по артикулу и наименованию), но исключает те, по которым были движения в регистре ТоварыНаСкладах:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Артикул В (
        ВЫБРАТЬ Артикул 
        ИЗ Справочник.Номенклатура 
        СГРУППИРОВАТЬ ПО Артикул, Наименование 
        ИМЕЮЩИЕ КОЛИЧЕСТВО(Ссылка) > 1
    )
    И НЕ Номенклатура.Ссылка В (
        ВЫБРАТЬ РАЗЛИЧНЫЕ Номенклатура 
        ИЗ РегистрНакопления.ТоварыНаСкладах
    )

Такой подход позволяет одним махом отобрать «чистые» дубли, которые гарантированно можно удалять без нарушения ссылочной целостности.

Метод 4: Прямое удаление через SQL (только для экспертов)

Если ссылок на объекты гарантированно нет (например, это ошибочно загруженные прайсы), можно использовать прямое удаление средствами СУБД. Это самый быстрый способ, так как он обходит все уровни платформы 1С. Однако помните о рисках: 1С хранит данные справочников в нескольких таблицах (основная, табличные части, дополнительные реквизиты). Удаление только из основной таблицы приведет к появлению «битых» данных.

Пример структуры SQL-запроса для удаления (нужно подставить имена таблиц конкретной базы):


-- Будьте крайне осторожны! Сначала сделайте бэкап.
DELETE FROM _Reference123 
WHERE _IDRRef IN (
    SELECT ID FROM #TempTableForDeletion
)

Важный совет: после прямого удаления через SQL обязательно выполните Тестирование и исправление в конфигураторе (пункты «Проверка логической целостности» и «Очистка пустых ссылок»).

Метод 5: Распараллеливание процессов

Если сервер обладает достаточными мощностями, процесс можно ускорить, запустив удаление в несколько потоков. Для этого:

  1. Разделите весь массив удаляемых ссылок на несколько частей (например, по первой букве кода или GUID).
  2. Запустите несколько фоновых заданий или сеансов обработки.
  3. Каждый поток должен работать со своим диапазоном данных, чтобы минимизировать взаимоблокировки (Deadlocks).

Как показывает практика, запуск в 4–8 потоков может сократить время удаления в несколько раз, при условии, что дисковая подсистема сервера справляется с нагрузкой на журнал транзакций.

Резюме и практические советы

Подведем итоги нашего анализа. Для достижения максимальной скорости при удалении миллионов записей придерживайтесь следующего алгоритма:

Проанализировав результаты тестов, можно утверждать: грамотное использование транзакций и отказ от лишних проверок позволяют удалять более 1 миллиона позиций за несколько часов, что является отличным результатом для платформы 1С.

← На главную