Когда мы сталкиваемся с необходимостью загрузки больших объемов данных из XML-файлов в базу 1С:Предприятие, особенно при переходе или миграции между системами, скорость этого процесса становится критически важной. Часто пользователи замечают, что в файловом режиме работы 1С загрузка XML происходит значительно быстрее и успешнее, чем в клиент-серверном режиме, несмотря на то, что серверные базы обычно демонстрируют более высокую производительность в повседневной работе. В этой статье мы подробно разберем, почему возникает такая ситуация, и какие шаги мы можем предпринять для оптимизации и ускорения загрузки данных в клиент-серверной конфигурации.
В нашем примере, автор столкнулся с тем, что передача НСИ, начальных остатков и документов за полгода из УПП 1.3.203 в КА 2.5 занимает минуты при выгрузке, но сутками и безуспешно при загрузке в серверную базу КА. При этом, выгрузив КА в файловую версию, загрузка успешно завершилась с ощутимым приростом скорости. Давайте выясним, почему так происходит и как с этим бороться.
Мы проанализируем основные факторы, которые могут влиять на скорость загрузки XML-данных в клиент-серверном режиме 1С.
Блокировки транзакций и уровни изоляции
В клиент-серверном режиме, где мы используем СУБД (например, SQL Server), система активно управляет блокировками транзакций. Этот механизм обеспечивает согласованность данных, но при массовой загрузке может создавать значительные накладные расходы.
Накладные расходы на журнал транзакций: Каждая операция вставки строки в SQL Server генерирует записи в журнале транзакций. Это существенно увеличивает нагрузку на дисковую подсистему. Мы можем оптимизировать этот процесс, используя минимальное логирование (minimally logged operations) в SQL Server. Для этого необходимо настроить соответствующую модель восстановления базы данных (например, BULK_LOGGED или SIMPLE). Это значительно сократит объем журнала транзакций и, как следствие, повысит производительность загрузки.
Избыточные блокировки: При большом количестве операций вставки, если каждая запись обрабатывается как отдельная транзакция (автокоммит), возникают накладные расходы на получение и снятие блокировок для каждой операции. Это приводит к потреблению ресурсов процессора и увеличению внутреннего времени ожидания в СУБД. Мы можем сделать загрузку более эффективной, используя явные транзакции в коде 1С. Объединение нескольких операций вставки в одну транзакцию (BEGIN TRAN...COMMIT) уменьшит накладные расходы на логирование и частоту сброса буферов журнала транзакций на диск.
Обработка данных по одной записи против пакетной обработки
В файловой базе 1С платформа может напрямую манипулировать данными, минимизируя накладные расходы. В клиент-серверном режиме каждая операция записи или модификации объекта 1С преобразуется в SQL-запросы, которые отправляются на сервер. Если мы загружаем данные по одной записи, с индивидуальным сохранением и проведением, это приводит к огромному количеству сетевых запросов и значительным накладным расходам на каждый вызов СУБД.
Платформа 1С:Предприятие оптимизирует загрузку данных из базы партиями фиксированного размера, но нам следует и в наших правилах обмена стремиться к пакетной обработке. Для потенциально неограниченных наборов данных рекомендуется извлекать и обрабатывать данные из базы партиями фиксированного размера, чтобы избежать загрузки всего результата запроса в оперативную память.
Бизнес-логика и фоновые задания
При загрузке данных, особенно документов, часто автоматически выполняется сложная бизнес-логика. Это может быть проведение документов, пересчет итогов регистров, контроль остатков, а также запуск различных фоновых заданий. Эти операции могут быть чрезвычайно ресурсоемкими и приводить к значительным задержкам, особенно в серверной базе, где они вызывают дополнительные обращения к СУБД и блокировки.
Отключение фоновых заданий: Как мы видим из сообщения автора, отключение фоновых заданий в свойствах базы на время загрузки помогло. Фоновые задания могут постоянно выполняться во время загрузки документов, генерируя ошибки и потребляя ресурсы. Мы можем отключить их, чтобы уменьшить нагрузку на сервер.
Оптимизация правил обмена: Этот пункт является одним из самых критичных. Стандартные правила обмена часто предусматривают проведение документов сразу после их записи. Это приводит к цепочке ресурсоемких операций: запись, проведение, пересчет итогов, проверка контролей. Мы можем значительно ускорить процесс, если:
Записываем объекты без проведения: В правилах конвертации объектов (ПКО) указываем только запись объекта, не вызывая процедуру проведения. Ссылки на загруженные, но не проведенные документы, мы можем сохранять в некий временный список (например, в массив или временную таблицу).
Пакетное проведение: После полной загрузки всех объектов или определенной партии, мы можем пройтись по этому списку в глобальном обработчике обмена и провести документы пакетом. Например, можно использовать такую логику:
// В обработчике ПослеЗагрузкиОбъекта для документов
// Если это документ, добавляем его ссылку в список для последующего проведения
Если ТипЗнч(Объект) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
Если Не ОбменДанными.Загрузка Тогда
// Запись документа без проведения
Объект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;
// Добавляем ссылку на документ в глобальный список для проведения
Если Не ЗначениеЗаполнено(ДополнительныеСвойства.СписокДокументовДляПроведения) Тогда
ДополнительныеСвойства.СписокДокументовДляПроведения = Новый СписокЗначений;
КонецЕсли;
ДополнительныеСвойства.СписокДокументовДляПроведения.Добавить(Объект.Ссылка);
КонецЕсли;
// В обработчике ПослеЗагрузкиДанных для всей выгрузки
Если ДополнительныеСвойства.СписокДокументовДляПроведения <> Неопределено Тогда
Для Каждого ЭлементСписка Из ДополнительныеСвойства.СписокДокументовДляПроведения Цикл
Попытка
ДокументОбъект = ЭлементСписка.ПолучитьОбъект();
Если ДокументОбъект.Проведен Тогда
Продолжить;
КонецЕсли;
// Здесь можно добавить проверку на режим проведения
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ЗаписатьЖурналРегистрации("ОбменДанными", УровеньЖурналаРегистрации.Ошибка, , ЭлементСписка, "Ошибка проведения документа: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецЕсли;
Обратите внимание, что переменная ДополнительныеСвойства.СписокДокументовДляПроведения должна быть доступна глобально или передаваться между обработчиками обмена. Это лишь пример, реальная реализация может потребовать более сложной архитектуры.
Отключение итогов регистров: На время массовой загрузки и проведения документов, мы можем временно отключить автоматический расчет итогов регистров, а затем, после завершения всех операций, включить их и пересчитать разом. Это значительно снизит нагрузку на систему, так как каждый пересчет итогов требует значительных ресурсов.
Накладные расходы на парсинг XML и работу с большими файлами
Обработка больших XML-файлов в 1С также имеет свои особенности. Если мы используем объекты, которые загружают весь файл целиком в оперативную память (например, DOMDocument), это может привести к значительному потреблению ОЗУ и замедлению работы, особенно если объем файла составляет сотни мегабайт или гигабайты.
Использование потоковых методов: Для эффективной работы с большими XML-файлами и экономии памяти рекомендуется использовать потоковые методы чтения и записи. Объекты XMLReader и XMLWriter позволяют нам обрабатывать данные по частям, не загружая весь файл в память одновременно. Это значительно уменьшает потребление ресурсов.
Помимо этого, ненужные пробелы и избыточное использование пространств имен в XML также могут незначительно влиять на производительность парсинга, хотя их влияние обычно менее критично, чем другие факторы.
Конфигурация SQL Server и особенности работы
Производительность SQL Server, на котором работает наша клиент-серверная база 1С, сильно зависит от его конфигурации. Неправильные настройки могут существенно замедлить процесс загрузки данных.
Параметры сервера: Мы должны обратить внимание на следующие настройки:
tempdb: Неправильно настроенные файлы tempdb (например, недостаточное количество файлов для процессоров, некорректный размер) могут стать "бутылочным горлышком".cost threshold for parallelism: Значение по умолчанию (5) может приводить к чрезмерному распараллеливанию для средних операций, что не всегда эффективно. Попробуйте увеличить это значение.Оптимизация для "Ad hoc Workloads": Если в SQL Server используется механизм кэширования планов выполнения запросов, большое разнообразие запросов от 1С (что характерно для типовых конфигураций) может привести к заполнению кэша планами, которые редко используются повторно. Это потребляет память и снижает эффективность. Оптимизация для "Ad hoc Workloads" (например, включение опции optimize for ad hoc workloads) может помочь в таких случаях.
XML-индексы и SQL-функции: Если мы работаем с XML-данными, хранящимися непосредственно в SQL Server (например, в XML-столбцах), создание XML-индексов может значительно ускорить запросы к этим данным. Однако, при использовании SQL-функций для парсинга XML, таких как OPENXML или xml.nodes(), производительность может сильно зависеть от размера файла. Для очень больших XML-файлов (сотни мегабайт) эти методы могут быть медленными. В некоторых случаях использование подсказки запроса OPTION (MAXDOP 1) для таких запросов может помочь, предотвращая неэффективное распараллеливание.
Специализированные инструменты: Для очень сложных и объемных ETL-операций (Extract, Transform, Load), требующих глубоких преобразований, мы можем рассмотреть использование специализированных инструментов, таких как SQL Server Integration Services (SSIS), которые могут обеспечить лучшую производительность за счет нативной работы с данными на уровне СУБД.
Теперь, когда мы понимаем потенциальные причины, давайте соберем все знания и составим план действий для оптимизации процесса загрузки.
Оптимизация правил обмена
Это, пожалуй, самый важный аспект, поскольку он напрямую связан с тем, как 1С обрабатывает каждый объект. Мы должны стремиться к минимальному количеству операций с базой данных для каждого загружаемого объекта.
Запись без проведения: В наших правилах конвертации объектов (ПКО) для документов мы должны изменить стандартное поведение. Вместо того чтобы сразу проводить документ, мы должны только записать его. Например, в обработчике ПриЗагрузке или ПослеЗагрузкиОбъекта для объектов-документов, мы убеждаемся, что режим записи установлен в РежимЗаписиДокумента.Запись, а не РежимЗаписиДокумента.Проведение.
Пакетное проведение документов: После того как все документы (или большая их часть) будут загружены и записаны, мы можем запустить отдельную процедуру, которая пройдет по списку этих документов и проведет их пакетом. Для этого можно:
Провести() или Записать(РежимЗаписиДокумента.Проведение) для каждого документа. Это позволит нам выполнить все проверки и движения регистров одним большим пакетом, а не по отдельности для каждого документа.Отключение итогов регистров: На время массовой загрузки и последующего пакетного проведения, мы можем временно отключить механизм автоматического расчета итогов для ресурсоемких регистров. После завершения всех операций мы включим итоги обратно и выполним их принудительный пересчет (например, с помощью регламентного задания или специальной обработки). Это снизит нагрузку на СУБД, так как ей не придется постоянно пересчитывать итоги при каждом движении.
Управление фоновыми заданиями
Как показал опыт автора, фоновые задания могут активно мешать загрузке. Мы можем временно отключить их в свойствах базы данных на время загрузки. Для этого зайдем в конфигуратор, выберем нужную базу, перейдем в Администрирование -> Регламентные задания и установим флажок Задания регламентных заданий включены в положение "Выключено". После завершения загрузки обязательно включите их обратно.
Если это невозможно или нежелательно (например, если есть критически важные фоновые задания), мы можем проанализировать журнал регистрации, чтобы выявить, какие именно фоновые задания вызывают ошибки или слишком долго выполняются во время загрузки, и временно отключить только их или оптимизировать их работу.
Настройка SQL Server
Мы должны убедиться, что SQL Server настроен оптимально для работы с 1С:
Файлы tempdb: Убедитесь, что количество файлов tempdb соответствует количеству логических ядер процессора (или хотя бы их половине), и что они имеют оптимальный размер и расположены на быстрых дисках.
Память: Выделите достаточно памяти для SQL Server (обычно 70-80% от общего объема ОЗУ сервера), чтобы буферный кэш мог эффективно работать.
Модель восстановления: Рассмотрите возможность использования модели восстановления BULK_LOGGED или SIMPLE на время массовой загрузки, чтобы уменьшить объем журнала транзакций. После загрузки вернитесь к исходной модели.
Параллелизм: Экспериментируйте со значением cost threshold for parallelism и max degree of parallelism (MAXDOP). Например, установка MAXDOP = 1 для отдельных запросов или для всего сервера может быть полезна при массовой загрузке, чтобы избежать неэффективного распараллеливания.
Оптимизация для Ad hoc Workloads: Включите опцию optimize for ad hoc workloads в SQL Server, если кэш планов заполняется множеством уникальных коротких запросов, что характерно для 1С.
Работа с большими XML-файлами
Если размер XML-файла очень большой (сотни мегабайт или гигабайты), мы должны использовать потоковую обработку, чтобы избежать переполнения оперативной памяти:
XMLReader и XMLWriter: Вместо того чтобы загружать весь XML-файл в память с помощью ДокументXML или ФабрикаXDTO, мы можем использовать объекты XMLReader для чтения данных по частям и XMLWriter для записи. Это позволяет обрабатывать данные поэлементно, значительно снижая потребление памяти.
Разбиение файла: Если это возможно, мы можем разбить исходный большой XML-файл на несколько более мелких файлов и загружать их поочередно. Это уменьшит нагрузку на систему при обработке каждого отдельного файла.
Применение этих комплексных мер позволит нам значительно ускорить процесс загрузки XML-данных в клиент-серверную базу 1С, превратив "суточные и безуспешные" операции в успешные и быстрые, как это было замечено в файловой версии.