В процессе эксплуатации крупных информационных систем на базе 1С программисты часто сталкиваются с проблемой возникновения большого количества дублирующихся элементов справочников. Особенно остро этот вопрос встает после некорректного переноса данных через «Конвертацию данных» или при интеграции с внешними системами. Когда количество дублей исчисляется тысячами (например, более 1500 групп), стандартная обработка «Поиск и удаление дублей» может потреблять слишком много ресурсов, вызывать переполнение лога транзакций или просто «умирать» по таймауту. Рассмотрим, как решить эту задачу различными методами: от оптимизации штатных средств до низкоуровневых манипуляций в MS SQL Server.
Разберем ситуацию: типовая обработка в конфигурациях на БСП пытается выполнить поиск и замену ссылок в рамках одной или нескольких крупных транзакций. Когда система находит сотни мест использования для каждой из 1500 ссылок-дублей, объем изменяемых данных становится критическим. Процессорное время тратится на анализ метаданных, поиск по всем таблицам базы данных и проверку бизнес-логики в модулях объектов. Если база работает в режиме 24/7, длительная блокировка таблиц недопустима.
Проанализируем самый безопасный путь — разделение задачи на части. Вместо того чтобы пытаться обработать все 1500 дублей сразу, выполним следующие шаги:
Такой подход позволяет использовать отлаженные механизмы платформы, сохраняя целостность данных и не блокируя работу всей организации.
Если ручное разделение на части занимает слишком много времени, напишем собственную обработку. Рассмотрим алгоритм, который будет программно находить дубли по ключевым полям ИНН и КПП, а затем заменять ссылки порциями.
Сначала выполним запрос для поиска групп дублей:
ВЫБРАТЬ
Контрагент.ИНН КАК ИНН,
Контрагент.КПП КАК КПП,
КОЛИЧЕСТВО(Контрагент.Ссылка) КАК КоличествоДублей
ПОМЕСТИТЬ ВТ_Дубли
ИЗ
Справочник.Контрагенты КАК Контрагент
ГДЕ
Контрагент.ЭтоГруппа = ЛОЖЬ
СГРУППИРОВАТЬ ПО
Контрагент.ИНН,
Контрагент.КПП
ИМЕЮЩИЕ
КОЛИЧЕСТВО(Контрагент.Ссылка) > 1
;
ВЫБРАТЬ
Контрагент.Ссылка КАК Ссылка,
ВТ_Дубли.ИНН,
ВТ_Дубли.КПП
ИЗ
Справочник.Контрагенты КАК Контрагент
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Дубли КАК ВТ_Дубли
ПО Контрагент.ИНН = ВТ_Дубли.ИНН
И Контрагент.КПП = ВТ_Дубли.КПП
УПОРЯДОЧИТЬ ПО
ВТ_Дубли.ИНН
После получения списка дублей нам необходимо выбрать один «эталонный» элемент (например, самый ранний по дате создания или имеющий заполненные реквизиты) и заменить все остальные ссылки на него. Для этого воспользуемся методом ЗаменитьСсылки(), но будем вызывать его в цикле для небольших пакетов данных.
Важный момент: при программной замене обязательно устанавливайте свойство ОбменДанными.Загрузка = Истина. Это позволит избежать выполнения тяжелых проверок в модулях объектов, которые при массовой замене могут затормозить процесс в десятки раз.
Рассмотрим использование профессионального инструментария, такого как «Инструменты разработчика» (авторства Сергея Старых). В этом расширении или обработке есть продвинутые механизмы поиска и замены значений. Проанализируем их преимущества:
Иногда возникают ситуации, когда нужно заменить текстовые данные (например, строковое представление ИНН), которые хранятся не как ссылки, а как обычный текст в различных таблицах. Выясним, как это сделать на уровне базы данных, но помните о рисках нарушения целостности.
Для глобального поиска и замены в SQL можно использовать динамический скрипт. Однако, в контексте 1С, замена дублей контрагентов — это чаще всего замена Binary(16) (UUID ссылки), а не текста. Если же вам нужно заменить именно текст (например, ошибочно записанный «абв» на «агд» во всех текстовых полях), можно использовать следующий подход:
-- ПРИМЕР: Поиск и замена текста в конкретной таблице
UPDATE _Reference15 -- Имя таблицы справочника контрагентов в SQL
SET _Fld1234 = REPLACE(_Fld1234, 'абв', 'агд')
WHERE _Fld1234 LIKE '%абв%';
Выясним, почему этот метод опасен для 1С:
_Version не обновится корректно, что может вызвать ошибки при последующей записи объекта из интерфейса 1С.Проанализируем ситуацию, описанную в сообщениях форума: ИНН и КПП могут дублироваться не только в справочнике «Контрагенты», но и в других местах, таких как:
ОрганизацииКлассификаторОрганизацийЕГАИСХозяйствующиеСубъектыВетИСПри замене ссылок на контрагента 1С автоматически обновит записи в регистрах, где Контрагент является измерением или ресурсом. Однако, если ИНН записан как независимый строковый реквизит (собственный реквизит регистра), типовая замена ссылок его не тронет. В этом случае придется дополнительно пройтись по таким регистрам программным перебором.
Рассмотрев все варианты, мы рекомендуем придерживаться следующего плана действий:
1. Сделайте резервную копию базы данных. Это обязательный шаг перед любыми массовыми операциями.
2. Попробуйте выполнить замену штатными средствами, но малыми порциями (через фильтры в обработке).
3. Если штатные средства не подходят, используйте программный цикл с использованием метода ЗаменитьСсылки() и обязательным флагом ОбменДанными.Загрузка = Истина. Это обеспечит максимальную производительность при сохранении ссылочной целостности.
4. К прямому SQL-запросу UPDATE прибегайте только в самом крайнем случае, если нужно исправить тысячи строк в текстовых полях, которые не связаны с бизнес-логикой и итогами регистров, и только после полной остановки сервера приложений 1С для очистки кэша.
Помните, что 1500 дублей — это значительный объем, требующий аккуратности. Правильный подход — это всегда сочетание автоматизации и контроля за целостностью данных.