Почему выгрузка данных в текстовый файл в 1С занимает слишком много времени и как её ускорить?

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

Ситуация, когда выгрузка относительно небольшого объема информации (например, 150 000 строк и 50 МБ) занимает до двух часов, является нештатной. В норме платформа 1С:Предприятие 8.3 способна обрабатывать и сохранять такой объем данных на диск за интервал от 10 до 60 секунд. Скорость менее 1 МБ в минуту указывает на критические архитектурные ошибки в программном коде или неоптимальную работу с файловой системой.

Проанализируем основные причины медленной работы механизма выгрузки и разберем по шагам, как оптимизировать алгоритм до максимальной производительности.

Шаг 1. Локализация узких мест через замер производительности

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

Выясним причину задержки по следующему алгоритму:

  1. Откроем конфигуратор и запустим сеанс в режиме отладки.
  2. В меню Отладка выберем пункт Замер производительности.
  3. Запустим операцию экспорта данных и после ее завершения (или принудительной остановки через несколько минут) остановим замер.
  4. Отсортируем строки отчета по графе Время (%), чтобы увидеть наиболее медленные процедуры и функции.

Шаг 2. Использование правильного объекта для записи файла

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

Для быстрой пакетной выгрузки необходимо использовать объект ЗаписьТекста. Он осуществляет потоковую буферизованную запись порциями, не перегружая память процесса.

Посмотрим на пример правильной инициализации и построчной записи:


ПутьКФайлу = "C:\Temp\Export_Data.csv";
Запись = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.UTF8);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    // Запись строки в буфер потока
    Запись.ЗаписатьСтроку(СформированнаяСтрока);
КонецЦикла;

Запись.Закрыть();

Шаг 3. Исключение запросов в цикле и обращений через точку

Критическое замедление алгоритма часто вызывают запросы внутри цикла обхода данных. Если для каждой из 150 000 строк выполняется даже простейший дополнительный запрос к базе данных или обращение к реквизитам ссылочного поля через точку (например, Выборка.Контрагент.ОсновнойМенеджер.Наименование), платформа генерирует сотни тысяч отдельных обращений к СУБД.

Разберем правила оптимизации выборки:

  1. Все необходимые поля из связанных таблиц и справочников должны соединяться непосредственно в тексте одного исходного запроса с помощью конструкций ЛЕВОЕ СОЕДИНЕНИЕ.
  2. Если данные рассчитываются сложными формулами, не хранящимися в базе, предварительно рассчитаем их регламентным заданием и сохраним в отдельный непериодический регистр сведений.
  3. Используем последовательный курсор Запрос.Выполнить().Выбрать() вместо предварительной выгрузки всей таблицы в память через Запрос.Выполнить().Выгрузить(), чтобы избежать лишней нагрузки на оперативную память сервера.

Шаг 4. Отключение проверок RLS (прав доступа)

Если регламентное или фоновое задание формируется от имени пользователя с ограниченными правами, механизм RLS (ограничение доступа на уровне записей) на лету дописывает в исходный запрос сложные подзапросы с проверкой прав на каждую строку и таблицу. При больших объемах это увеличивает время выполнения запроса в десятки раз.

Для фоновых выгрузок аналитических данных обязательно переведем выполнение кода в привилегированный контекст:


УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст = "...";
// Выполнение запроса без накладных расходов на проверку прав
Результат = Запрос.Выполнить();
УстановитьПривилегированныйРежим(Ложь);

Шаг 5. Оптимизация форматирования и сборки строк

При выгрузке 25 колонок на 150 000 строк платформа обрабатывает 3,75 миллиона отдельных значений. Ошибки при формировании итоговой строки вызывают огромные затраты процессорного времени:

  1. Отказ от функции Формат() в теле цикла. Парсинг формата даты или числа миллионы раз создает сильную нагрузку на процессор. Необходимые строковые представления (например, год, месяц или представление ссылок) следует получать прямо в запросе с помощью встроенных функций языка запросов ПРЕДСТАВЛЕНИЕ(), ГОД() и других.
  2. Быстрое объединение колонок. Конкатенация строк через оператор + создает в памяти огромное количество временных строковых объектов. Намного быстрее заполнять массив значений строки и объединять их штатной функцией платформы СтрСоединить().

Посмотрим на пример эффективной сборки строки:


МассивКолонок = Новый Массив;
Пока Выборка.Следующий() Цикл
    МассивКолонок.Очистить();
    МассивКолонок.Добавить(Выборка.Код);
    МассивКолонок.Добавить(Выборка.ТоварНаименование);
    МассивКолонок.Добавить(Строка(Выборка.Количество));
    МассивКолонок.Добавить(Строка(Выборка.Сумма));
    
    // Сборка строки с разделителем-точкой с запятой за один вызов
    СтрокаФайла = СтрСоединить(МассивКолонок, ";");
    Запись.ЗаписатьСтроку(СтрокаФайла);
КонецЦикла;

Шаг 6. Исключение задержек файлового ввода-вывода (I/O)

Запись текстового файла построчно напрямую в сетевую папку (через сетевые протоколы SMB/DFS) драматически снижает скорость из-за сетевых задержек (RTT) и постоянного захвата файловых блокировок операционной системой на каждый блок данных. Дополнительно процесс может тормозить антивирусное ПО или DLP-системы, проверяющие файл на лету.

Для предотвращения проблем окружения применим следующий подход:

  1. Формируем итоговый файл исключительно локально на сервере 1С, используя системную функцию КаталогВременныхФайлов().
  2. Добавляем рабочий каталог кластера серверов 1С и временный каталог в список исключений антивирусного сканера.
  3. После того как файл полностью сформирован и закрыт методом Запись.Закрыть(), перемещаем его в сетевую директорию или папку назначения одной командой КопироватьФайл() или ПереместитьФайл().

Применение этих рекомендаций позволяет сократить время экспорта 50-мегабайтного массива данных с двух часов до 15–40 секунд без модификации аппаратной части сервера.

← На главную