При работе с крупными инсталляциями 1С:ERP часто возникает задача синхронизации справочников. Когда объем номенклатуры измеряется сотнями тысяч записей (например, 800 000 позиций), стандартные методы выгрузки через XML или COM-соединение могут занимать десятки часов или приводить к ошибкам нехватки памяти. В этой статье мы проанализируем ситуацию и разберем наиболее эффективные способы сравнения справочников, используя возможности SQL-сервера и оптимизированную работу с файлами.
Если обе базы данных находятся на одном сервере MS SQL (или на серверах, между которыми настроен Linked Server), это самый быстрый способ. Прямое сравнение таблиц позволяет выявить отсутствующие записи за считанные секунды или минуты. Выясним причину такой эффективности: SQL-сервер оптимизирует выборку на уровне индексов, не загружая объекты в память платформы 1С.
Рассмотрим пример простого SQL-запроса для поиска кодов номенклатуры, которые есть в первой базе, но отсутствуют во второй:
SELECT [_Code]
FROM [_BASE_1].[dbo].[_Reference32]
WHERE [_Code] NOT IN (SELECT [_Code] FROM [_BASE_2].[dbo].[_Reference32]);
Важно: имена таблиц (например, _Reference32) и полей в каждой базе могут отличаться. Чтобы узнать имя таблицы справочника в SQL, используйте функцию платформы ПолучитьСтруктуруХраненияБазыДанных().
Для более сложной проверки, включающей сравнение реквизитов (наименование, артикул, характеристики), рекомендуется использовать оператор EXCEPT, который возвращает только уникальные строки, отсутствующие во втором наборе данных:
SELECT [_Code], [_Description], [_Fld1234] FROM [_BASE_1].[dbo].[_Reference32]
EXCEPT
SELECT [_Code], [_Description], [_Fld1234] FROM [_BASE_2].[dbo].[_Reference32];
Если прямое сравнение через SQL-запрос выполнить невозможно (например, базы на разных серверах без прямой связи), можно использовать объект ADODB.Connection. Это позволит выполнить запрос к одной базе и сравнить результат с данными текущей базы. Рассмотрим пример функции для установки соединения:
Функция УстановитьСоединениеСSQL(стрПараметры)
строкаПодключения = "driver={SQL Server};server="+ стрПараметры.серверИмя +
";uid="+ стрПараметры.серверПользователь +
";pwd="+ стрПараметры.серверПароль+
";database="+ стрПараметры.серверБаза +
";trusted_connection=yes";
АДОДБКоннект = Новый COMОбъект("ADODB.Connection");
Попытка
АДОДБКоннект.ConnectionTimeout = 0;
АДОДБConnect.Open(строкаПодключения);
Возврат АДОДБКоннект;
Исключение
Сообщить("Ошибка соединения: " + ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
После установки соединения мы можем прочитать данные во временную таблицу или таблицу значений и выполнить поиск. Однако при объеме в 800 000 строк загрузка в ТаблицаЗначений может потребовать значительного объема оперативной памяти. В этом случае лучше обрабатывать данные порциями (используя SELECT TOP... или OFFSET...FETCH).
Если архитектура систем требует передачи файла, забудьте про формат XML для таких объемов. XML-файл на 800 тысяч позиций со всеми характеристиками может достигать объема 60 ГБ и более. Разберем, как правильно организовать выгрузку, чтобы не «уронить» систему по памяти.
Использование объекта ЗаписьТекста позволяет записывать данные построчно сразу на диск, не накапливая их в памяти. Посмотрим на пример кода:
ПутьКФайлу = "C:\Exchange\nomenclature_diff.csv";
Файл = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.UTF8);
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Код, Наименование, Артикул ИЗ Справочник.Номенклатура";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СтрокаДанных = Выборка.Код + ";" + Выборка.Наименование + ";" + Выборка.Артикул;
Файл.ЗаписатьСтроку(СтрокаДанных);
КонецЦикла;
Файл.Закрыть();
Преимущества этого метода:
Bulk Insert или обрабатываются скриптами.Традиционное COM-соединение часто критикуют за медлительность при обращении к каждому объекту (СоздатьЭлемент(), Записать()). Проанализируем, как ускорить этот процесс. Вместо того чтобы в цикле обращаться к Соединение.Справочники..., можно выполнить запрос внутри COM-соединения, который вернет примитивные типы данных (строки, числа), и передать эти данные в основную базу одним массивом или таблицей.
Также существует миф, что COM не поддерживается на 64-битных платформах. На самом деле он поддерживается, но требует настройки в компонентах DCOM (создание пустого приложения COM+ для библиотеки comcntcfg.xml), чтобы 64-битный рабочий процесс сервера 1С мог корректно взаимодействовать с 32-битными библиотеками, если таковые используются.
При сравнении справочников номенклатуры в ERP недостаточно просто найти отличия в кодах. Рассмотрим ключевые моменты, которые необходимо учесть:
УникальныйИдентификатор() (GUID). Коды могут дублироваться или переназначаться, а GUID гарантирует однозначное соответствие элементов в разных базах.ВидыНоменклатуры, ЕдиницыИзмерения, ГруппыДоступа. Если вы создаете номенклатуру через SQL, вы рискуете получить «битые» ссылки.Объект.Записать()).Таким образом, для разовой акции по синхронизации 800 000 позиций оптимальным будет: выгрузить идентификаторы и хеш-сумму ключевых полей (Наименование + Артикул) в CSV-файл из обеих баз, сравнить их с помощью SQL или простой обработки и догрузить только недостающие или изменившиеся записи штатными средствами 1С.