Язык мой – враг мой
Растущие объемы данных требуют новых подходов к разработке и горизонтального маштабирования, однако язык программирования 1С является сдерживающим фактором. Как можно обойти ограничения языка программирования 1С?
- Описание
- Подробнее
Описание
Платформе 8.х почти 19 лет, идет ли она в ногу со временем?
На сайте releases.1c.ru первые релизы 1с 8.х датируются 2003 годом. В промышленной эксплуатации был оперативный учет, а бухгалтерский и механизм сложных периодических расчетов (зарплата) были в бэта тестировании.
С тех пор платформа до версии 8.3 нарастила функционал во многих направлениях, казалось бы там есть все что нужно для автоматизации учета , создания веб\мобильных приложений, готовые типовые конфигурации. Беглый просмотр архитектуры https://v8.1c.ru/platforma/ вызывает желание автоматизировать все, что возможно на предприятии напр. полную цепочку от продаж до учета. Если оценивать запас прочности системы на рост данных, объема операций, подключений – платформа предлагает масштабируемый на нужное число серверов сервер приложений 1С. Механизм фоновых заданий позволяет обрабатывать наборы операций (пакеты) параллельно.
Неужели у нас есть все что нужно для комфортного внедрения и можно спокойно смотреть в будущее? К сожалению, нет и проблема кроется в организации языка программирования 1С, он изначально не рассчитан на горизонтальное масштабирование. Под горизонтальным масштабированием подразумевается:
«разбиение системы на более мелкие структурные компоненты и разнесение их по отдельным физическим машинам (или их группам), и (или) увеличение количества серверов, параллельно выполняющих одну и ту же функцию. Масштабируемость в этом контексте означает возможность добавлять к системе новые узлы, серверы для увеличения общей производительности. Этот способ масштабирования может требовать внесения изменений в программы, чтобы программы могли в полной мере пользоваться возросшим количеством ресурсов»
Термин допускает разные трактовки в зависимости от архитектуры и задач (пример https://www.oreilly.com/library/view/cloud-architecture-patterns/9781449357979/ch01.html )
Кстати фирма 1С под масштабируемостью подразумевается совсем другое https://v8.1c.ru/platforma/masshtabiruemost/
Именно сейчас горизонтальное маcштабирование важно, поскольку любое предприятие имеет возможности в несколько раз увеличить количество продаж, сделок, заказов и т.д. за счет
- Интернет продаж\мобильных приложений
- Электронных платежей.
- Применение роботов в обработке заказов\сделок. Напр на фондовом рынке большинство сделок создается роботами или автоматизированными процедурами.
И естественно предприятие будет использовать приложение, которое адаптировалось под определенную бизнес модель и допустим эта модель успешно увеличила количество сделок\заказов. Поскольку каждая операция в фронт офисе, порождает операции в бэкофисе, бухгалтерии и управленческом учете – объем операций увеличивается в разы. Не все можно победить агрегацией на разных уровнях, как по организационным, так и по техническим причинам. Если не думать об этом в самом начале — получится, что с прикладной точки зрения система полностью соответствует бизнес процессам компании, а с технической уже не может справится с объемом данных.
В теории архитектор (эта специальность уже становится необходимостью в проектах внедрения 1С) должен договорится с заказчиком\ключевым пользователем\руководителем проекта от бизнеса о границах маcштабирования. Проблема в том, что они сами не знают с чем столкнутся через 5 лет, а приложение нужно уже сейчас, тем более 1С предлагает привлекательные готовые типовые конфигурации из коробки, которые можно «немного доработать и все». Поэтому на практике архитектор может построить только масштабируемую архитектуру, но как раз в 1С все ограничено структурой языка программирования в первую очередь.
Конечно можно предложить рассмотреть конструктор на стеке Java, С# в связке с любимой СУБД ,но нужно понимать, что они не для прикладного программирования, без полноценных RAD (Rapid application development) инструментов и там вообще ничто не ограничивает от плохих архитектурных решений, кроме опыта, знаний и правильного понимания архитектурных паттернов. Плюс цена такого решения будет в разы дороже. Далее рассматриваются решения с максимальным использованием возможностей 1С. Я знаю что кто-то пишет\читает напрямую в\из базу SQL и использует недокументированные возможности, но с RAD это не имеет ничего общего лучше каждый инструмент использовать по назначению.
Анонс. (далее нерешенные темы анонсируются как темы отдельных статей, по просьбам трудящихся ;)): У разработчика на 1С достигшего уровня гуру 1С возникает соблазн строить архитектуру вокруг 1С. Если же разработчик знает технологии реализованные на Java или C# возможности интеграции 1С с другими приложениями кажутся скромными. Приходит осознание, что 1С это всего лишь один из сервисов с ограниченным функционалом и правильней строить архитектуру как микросервисную, где 1С это сервис хоть и не микро.
Далее примеры будут приводится для финансового учета операций с фондового рынка ценных бумаг, где приходится работать с исходными сделками импортируя их без агрегации в количестве около 1 миллиона в день, а количество изменений (связанные реквизиты, трансферы, изменения реквизитов или трансферов) по ним около 4-6 миллионов в день.
Если под операцией понимать сделку на фондовом рынке, продажу, заказ, платеж и т.д ситуация будет выглядеть аналогичной
Разберем кейс на примере: Сообщения с изменениями операций поступают в шину RabbitMQ . Оттуда их считывает процесс Message Reader и сохраняет сообщения в индексированный буфер. Данные из буфера читаются кластером 1С и преобразуются в документы, записи регистров сведений 1С и сохраняются в базу.

Влияние языка программирования 1С на масштабирование приложений.
Импорт данных
Давайте сначала попробуем максимально быстро импортировать операции. В 1С есть возможность разбить наборы данных (операции\платежи\ сделки ) на массивы фиксированного размера (далее пакет) , и запустить на исполнение фоновыми заданиями в нужном количестве (40 параллельных заданий вполне оптимально для одного современного двухпроцессорного сервера приложений).
Попробуем через документ
Документ не аргумент.
Для операций в 1С предусмотрены метаданные типа Документ и для определенных случаев можно применять БизнесПроцессы, Задачи. При этом Документ естественно имеет преимущества – его можно записывать без проведения, логику создания проводок\движений в регистры вынести в отдельные параллельные обработки.
Возьмем Документ, мы можем передать 1000 xml в фоновое задание, создать 1000 документов в памяти, разыменовать ссылки на справочники одним запросом и … записывать каждый документ в пакете придется последовательно методом Документ.Записать() без проведения. Если посмотрите, как это отражается каждая запись в Profiler MSSQL станет еще грустнее .
Не забывайте что любая операция Документ.Записать() это на SQL сервере это как минимум поиск существующего документа, обновление таблиц, а если есть табличные части в документе то еще удаление\вставка.
Анонс Внутренняя трассировка через SQL Profiler операций записи, особенно в регистры, тянет на отдельную статью — там сразу видны все узкие места. Чаще всего в профайлере анализируют запросы на чтение напр //sale.itcity.ru/1c/articles/1492368/ , по анализу операций записи статей не встречал.
Можно закрыть глаза на эффективность обработки данных документов на уровне процессор – память , ведь это можно решить распараллеливанием, но запись на диск (даже SSD) уже будет узким местом.
Конечно когда 40 параллельных фоновых заданий пишут документы (пусть последовательно внутри задания) это дает надежду увеличить возможности кластера и увеличить их например до 80 и решить проблему оборудованием (напр много ядер и база на SSD полностью). Однако при таком количестве мелких DML (data manipulation language) операций SQL (не путать с транзакциям 1С\MS SQL ) вы неизбежно упретесь в возможности записи в MS SQL transaction log даже на уровне его процессов write log см статью
https://chrisadkin.io/2015/09/09/tuning-the-logcache_access-spinlock-on-a-big-box/
https://chrisadkin.io/2015/06/11/writelog-at-scale-going-beyond-you-need-faster-disks/
Это неочевидный момент – метод .Записать() создает несколько DML операций SQL . Помножьте это на количество операций и вы поймете какую нагрузку 1С создает на SQL Server которую можно наблюдать как количество BatchJobs в секунду . Даже если это заключить в НачатьТразнакцию \ ЗафиксироватьТранзакцию лучше не станет, ведь транзакция будет содержать не крупный DML оператор на 1000 записей, а больше 1000 маленьких
Анонс: С такой ситуацией столкнулся на практике при нагрузочном тесте кластера на VMWare, там очень много интересных эффектов проявилось при высокой нагрузке
Не случайно при разработке на MS SQL или Oracle рекомендуют укрупнять DML операции и транзакции до разумного предела. Кроме того обновление записи в таблице влечет еще и обновление индексов которых 1С создает немало см
https://its.1c.ru/db/metod8dev#content:1590:hdoc
Анонс: При высокой параллельной записи индексы серьезно затрудняют даже вставку (а обновление тем более) и есть особые рекомендации Microsoft на эту тему.
При таком устройстве языка программирования невозможно записать несколько документов в одном DML операторе
При такой организации языка возникает много запросов\ответов по сети. Обмен по сети между кластером 1С и SQL в этом случае уже требует Teamed lan , + процессорные ресурсы сервера , ведь траффик увеличивается и его кто-то должен обрабатывать на сервере даже если сетевая карта часть работы берет на себя.
Может быть, использовать Регистр сведений без регистратора как альтернативу Документу?
Конечно, на экзамене 1С будет оценка 2 за нецелевое использование, но если очень хочется, то можно. Можно построить , например, такой регистр сведений.
И да метод РегистрСведенийНаборЗаписей.<Имя регистра сведений>.Записать (Истина) позволяет добавить сразу несколько документов с разными ИдИсхСистемы. Это хорошо, но проблемы в языке 1С остаются
- Обновлять записи придется в рамках одного значения измерения ИдИсходнойСистемы. Ведь отбор в наборе записей может устанавливаться только на равенство (см справку).Это нивелирует все выигрыши если есть повторные обновления большинства документов (напр так устроена front office система).
- Если посмотреть MS SQL профайлер 1С использует при Update простые delete , insert по комбинации измерений, а не более эффективный merge
- Если у документа нужна табличная часть, ее придется помещать в отдельный регистр сведений и для связи с основной таблицей повторять в ней значения измерений основного документа. Вообще необходимость измерений, не дает рассматривать регистр сведений как простую таблицу (аналог табличной части документа). В этом примере невозможно добавить несколько одинаковых реквизитов с разными значениями. А простых таблиц в 1С не предусмотрено, если не считать трюки с регистром сведений у которого одно измерение УИД
Анонс: Запись можно ускорить еще больше если сделать эти регистры периодическими и писать версии операций. Запросы по таблицам несколько усложняются (нужно выбирать последние версии особым образом), но зато скорость импорта гораздо больше
Формирование движений в Регистры Бухгалтерии и Накопления с максимальной скоростью.
Я намеренно упустил регистры сложных периодических расчетов поскольку диапазон их практического применения ограничен расчетом зарплаты и начислением различной амортизации.
По производительности от медленных до быстрых рассматриваемые регистры располагаются так^
Тип регистра | Условие максимальной производительности |
Регистр Бухгалтерии , сложная структура дает более медленную производительность. | Итоги сдвинуты на прошлый месяц, текущие итоги отключены, разделение итогов включено. Запись в режиме РегистрБухгалтерииНаборЗаписей.<Имя регистра накопления> .ОбменДанными= Истина |
Регистр Накопления включенными итогами (остатки обороты). Производительность лучше чем у регистра бухгалтерии | Итоги сдвинуты на прошлый месяц, текущие итоги отключены, разделение итогов включено. Запись в режиме РегистрНакопленияНаборЗаписей.<Имя регистра накопления> .ОбменДанными= Истина |
Регистр Накопления (обороты) . Включены агрегаты регистра накопления. Наилучшая производительность поскольку итоги по оборотам считаются отдельной процедурой | Запись в режиме РегистрНакопленияНаборЗаписей.<Имя регистра накопления> .ОбменДанными= Истина |

