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