Разберем ситуацию, с которой часто сталкиваются разработчики при интеграции: необходимо загружать и обрабатывать текстовые файлы в формате CSV колоссальных объемов (например, 10 ГБ, около 150 колонок и миллионы строк). При использовании стандартного построчного чтения средствами платформы 1С этот процесс может занимать 6-7 часов, что категорически не подходит для ежедневных оперативных обменов.
Проанализируем причину такой низкой производительности. Главная проблема кроется не столько в самом доступе к диску, сколько во внутренних механизмах платформы 1С по работе с памятью. При вызове платформенных функций, таких как ПрочитатьСтроку и последующем разбиении через СтрРазделить, генерируются миллиарды объектов типа «строка». Сборщик мусора перегружается, что приводит к лавинообразному замедлению. Давайте посмотрим на практические методы решения этой задачи и выберем наиболее быстрый.
Прежде чем использовать сторонние технологии, рассмотрим, как можно выжать максимум из штатного объекта ЧтениеТекста. Если мы читаем файл по одной строке, возникают огромные накладные расходы на обращение платформы к файловой системе. Решением может стать чтение крупными блоками (чанками).
Вместо метода ПрочитатьСтроку используем метод Прочитать, в который передаем количество символов. Считывая данные огромными блоками в память, мы можем разбирать этот массив данных значительно быстрее, передавая обработку в фоновые задания (многопоточность).
Для понимания базовой скорости записи и чтения платформой рассмотрим синтетический тест (генерация и чтение файла на 14.5 ГБ):
&НаСервере
Процедура ТестЧтенияЗаписиНаСервере()
ИмяФайла = ПолучитьИмяВременногоФайла("txt");
СтрокаТекста = "";
Для инд = 1 По 150 цикл
СтрокаТекста = СтрокаТекста + "01234596789";
КонецЦикла;
Нач = ТекущаяДата();
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла);
Для инд = 1 По 7000000 цикл
ЗаписьТекста.ЗаписатьСтроку(СтрокаТекста);
КонецЦикла;
ЗаписьТекста.Закрыть();
Сообщить("Время записи " +(ТекущаяДата()-Нач) + " сек");
Нач = ТекущаяДата();
Чтение = Новый ЧтениеТекста(ИмяФайла);
Пока СтрокаТекста <> Неопределено Цикл
СтрокаТекста = Чтение.ПрочитатьСтроку();
КонецЦикла;
Сообщить("Время чтения " +(ТекущаяДата()-Нач) + " сек");
КонецПроцедуры
Само по себе "голое" чтение без обработки 7 миллионов строк может занять около 2 минут на мощном сервере. Остальные 4-5 часов уходят именно на разбор строк (парсинг).
Если стандартная функция СтрРазделить работает медленно или спотыкается о сложные переносы строк внутри закавыченных полей CSV, применим COM-объект VBScript.RegExp. Корректно написанное регулярное выражение позволит разобрать строку на нужные колонки с учетом всех экранирований значительно быстрее, чем ручной перебор символов.
Одним из самых популярных и надежных способов чтения объемных CSV-файлов является технология ADO. Для больших массивов данных использование провайдера Microsoft.Jet.OLEDB предпочтительнее построчного чтения 1С. Провайдер сам умеет понимать форматы дат, числа и многострочные текстовые поля внутри кавычек. Скорость парсинга может достигать около 3000 строк в секунду.
Важный нюанс: Опытным путем разработчики выявили, что чтение через ADO "без схемы" (когда мы не используем жесткую типизацию через файл Schema.ini) часто происходит быстрее, так как не тратится время на строгую валидацию типов.
Если данные из CSV требуются только для загрузки в регистры или сравнения, полностью исключим 1С из процесса первоначального чтения. Делегируем эту задачу серверу баз данных.
BULK INSERT (или COPY для PostgreSQL) для прямой заливки CSV-файла в таблицу. СУБД делает это с невероятной скоростью, недоступной для 1С.Таким образом, мы перекладываем тяжелую операцию чтения диска и парсинга текста на СУБД, которая оптимизирована для этих задач.
Для файлов размером 10-20 ГБ классические реляционные СУБД могут начать "задыхаться". В таких архитектурно-сложных случаях рассмотрим использование аналитической колоночной БД, такой как ClickHouse.
ClickHouse позволяет импортировать сырые CSV-файлы напрямую в свои таблицы со скоростью несколько гигабайт в секунду. После того как файл загружен в ClickHouse, мы из 1С можем делать к нему HTTP-запросы (или запросы через ODBC драйвер). ClickHouse мгновенно (за доли секунды) произведет группировку, фильтрацию или сравнение нового файла с предыдущим днем, отдав платформе 1С только готовую «дельту» изменений.
Если задача заключается не просто в чтении, а в предварительной аналитике (например, каждый день приходит 10 ГБ, и нам нужно сравнить его с файлом за прошлый день, чтобы найти изменившиеся строки), применим внешний скрипт.
Идеально подойдет язык Python и его библиотека Pandas. Скрипт на Python может прочитать 10-гигабайтный файл за пару минут, выполнить сравнение двух наборов данных в оперативной памяти и сформировать итоговый компактный CSV-файл (например, на 5 МБ), содержащий только обновленные записи. 1С останется лишь быстро загрузить эти 5 МБ штатными средствами. Для загрузки подготовленного файла в базу можно использовать обработку импорта данных из различных табличных форматов.
Альтернативно, можно использовать готовые Native API компоненты (DLL библиотеки на C++ или C#). Такие внешние компоненты, разработанные специально для 1С, загружают файлы по стандарту RFC 4180 и отдают в 1С уже готовые типизированные массивы структур, полностью обходя узкие места штатного интерпретатора.
Подведем итог. Если вы столкнулись с медленным чтением сверхбольших файлов в 1С, откажитесь от построчного парсинга объекта ЧтениеТекста. В зависимости от архитектуры проекта, выберите загрузку через BULK INSERT в СУБД, предварительную фильтрацию скриптами на Python или использование аналитических баз вроде ClickHouse. Это сократит время обработки с 6 часов до нескольких минут.