[ OData4 ]

Девять машинных прогонов 27 сентября 2026 на одной и той же базе, одних и тех же данных и одном веб-сервере. Ниже — условия стенда, набор запросов, все полученные цифры и отдельным разделом то, чего в этих цифрах нет. Без условий замера любое число на этой странице ничего не стоит, поэтому они идут первыми.

Стенд

Платформа 1С
8.3.27.1719
Тип базы
файловая
Веб-сервер
Apache на той же машине
Сеть
localhost — сетевая задержка исключена
Сжатие
выключено, клиент просит identity
Клиент замеров
Go, net/http, замер по httptrace
Итоговая цифра
медиана после прогрева; тяжёлые обходы — один проход
Разброс повторов
±10–20 %: машина была занята и другой работой

Что лежало в базе

Документы с табличными частями
100 тыс. документов, 1 млн строк
Записи регистра накопления
1 088 418
Записи регистра бухгалтерии
1 120 653
Элементы справочника
100 тыс.
Состав публикации
1 371 объект, 2 203 набора

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

Чего в этих цифрах нет

  • Одиночные мелкие запросы у нас немного медленнее штатного интерфейса: $top=1 — 28 мс против 14 мс.

  • Записи регистра бухгалтерии на миллион строк страницами по умолчанию отстают: 199 с против 124 с.

  • Всё мерено на файловой базе с Apache на той же машине. Клиент-серверная не замерена.

  • Одновременная работа многих клиентов не замерена.

  • Прогоны шли на машине, занятой и другой работой: разброс повторов ±10–20 %.

  • Первый $apply по миллиону записей на холодном кэше файловой базы занял 207 с, дальше — около 1,1 с.

  • Страница с продолжением по составному ключу на таблице в миллион строк дорожает до 4,4 с: похоже, в файловой базе условие продолжения не использует индекс.

Что сравнивалось

Три сущности на одной базе: OData4 с выдачей на языке 1С, OData4 с компонентой на Rust и штатный standard.odata. Адреса — /hs/odata/v4 и /odata/standard.odata одной и той же публикации, вход Basic под одним пользователем.

Полная выгрузка набора

секунды, меньше — лучше

Документы с табличными частями — единственный набор, где отрыв заметный: штатный интерфейс отдаёт их одним ответом на 3,8 ГБ и тратит на это больше четырёх минут. На записях регистра бухгалтерии мы, наоборот, отстаём.

  • Документы с табличными частями

    100 тыс. документов, ответ 3,5 ГБ

    OData4161–199 с
    standard.odata257–263 с
  • Записи регистра накопления

    1,09 млн записей

    OData4134 с
    standard.odata147 с
  • Записи регистра бухгалтерии

    1,12 млн записей — здесь мы медленнее

    OData4199 с
    standard.odata124 с
  • Справочник целиком

    100 тыс. элементов, ответ 154 МБ

    OData411,2 с
    standard.odata10,7 с

Объём ответа

гигабайты, меньше — лучше

Те же данные в более компактном JSON: на наборах записей регистров ответ примерно вдвое меньше. Это и трафик, и время разбора на стороне клиента.

  • Записи регистра накопления

    1,09 млн записей

    OData41,5 ГБ
    standard.odata3,3 ГБ
  • Записи регистра бухгалтерии

    1,12 млн записей

    OData41,1 ГБ
    standard.odata2,2 ГБ
  • Документы с табличными частями

    100 тыс. документов

    OData43,5 ГБ
    standard.odata3,8 ГБ

Короткие запросы

миллисекунды, меньше — лучше

Постоянная стоимость запроса у нас выше: своё маршрутизирование и своя модель стоят около десятка миллисекунд. На $metadata это окупается кэшем между сеансами — 28 мс против 402.

  • $metadata, тёплый сеанс

    описание модели, 5,4 МБ против 8,5 МБ

    OData428 мс
    standard.odata402 мс
  • Balance() регистра бухгалтерии

    ответ 1,9 МБ

    OData4230 мс
    standard.odata196 мс
  • $filter по номеру, 100 документов

    ответ 3,5 МБ

    OData4221 мс
    standard.odata182 мс
  • Turnovers() регистра накопления

    ответ 47 КБ

    OData418 мс
    standard.odata19 мс
  • Справочник, $top=1

    одна запись

    OData428 мс
    standard.odata14 мс

Выгрузки среднего размера

секунды, меньше — лучше

Здесь штатный интерфейс быстрее: он отдаёт всё одним ответом, а мы платим за страницы с продолжением. На таких объёмах разница в пару секунд, и ощутимой она становится только на гигабайтах.

  • Справочник целиком

    154 МБ

    OData411,7 с
    standard.odata10,7 с
  • Справочник, три поля

    13,9 МБ

    OData42,9 с
    standard.odata0,97 с
  • Документы, три поля

    10,5 МБ

    OData42,5 с
    standard.odata0,93 с

Что дала компонента на Rust

во сколько раз быстрее, чем выдача на языке 1С

Компонента необязательная: если её нет, сервис работает на языке 1С и отвечает теми же ответами, только медленнее. Там, где время уходит не на сериализацию, а на запрос страницы, выигрыш меньше — последний ряд.

  • Страница документов с табличными частями

    9 088 → 1 450 мс

    6,3 ×
  • Документы целиком, 3,5 ГБ

    992 → 161 с

    6,2 ×
  • Документы, три поля

    10,5 → 2,5 с

    4,2 ×
  • Справочник целиком, 154 МБ

    47,9 → 11,7 с

    4,1 ×
  • Записи регистра накопления, 1,5 ГБ

    853 → 471 с

    1,8 ×

Куда уходит время внутри 1С

миллисекунды, страница из 1000 документов

Запрос к базе и выгрузка результата занимают единицы миллисекунд, сериализация JSON — 93–97 % всего времени. Из этого разложения и выросло решение вынести выдачу в компоненту.

  • Сериализация JSON

    7 816 мс
  • Сборка строк табличных частей

    427–1 002 мс
  • Формирование ответа

    81 мс
  • Выгрузить()

    11 мс
  • Запрос к базе

    3 мс

Размер страницы решает

секунды, 1,09 млн записей регистра накопления

Один и тот же набор, разные настройки выдачи: разница между худшим и лучшим вариантом — почти вчетверо. Страницами по умолчанию OData4 отстаёт от штатного интерфейса, страницами по 5000 — догоняет, одним ответом — обходит.

  • Страницами по 1000

    1 089 запросов с продолжением

    493 с
  • Страницами по 5000

    218 запросов

    145 с
  • Одним ответом

    без @odata.nextLink

    134 с
  • standard.odata, одним ответом

    ответ 3,3 ГБ вместо 1,5 ГБ

    147 с

Все таблицы протокола

Ниже — полные прогоны, из которых собраны графики выше: четыре объёма базы, разложение времени внутри 1С, выбор способа передачи данных в компоненту и запись.

Демобаза без сгенерированных данных

Медиана по трём повторам, мс. Выдача OData4 — на языке 1С.

ЗамерOData4standard.odata
Страница документов1 004153
Документы целиком1 004156
Документы, три поля2412
Документы, $filter1213
Строки табличной части целиком25163
Строки табличной части, $expand604198
Справочник, $top=12613
Справочник целиком4316
Справочник, три поля911
Записи регистра накопления1 153229
Записи регистра бухгалтерии6 8041 304
Turnovers()2618
Balance() регистра бухгалтерии762182
$apply10—
$batch, 50 операций829—
$metadata XML, тёплый25396
$metadata JSON, тёплый24—

Ступень 1000 документов

Медиана, мс. Выдача OData4 — на языке 1С: именно эти цифры и стали поводом написать компоненту.

ЗамерOData4standard.odataОбъём ответа
Страница документов, 44 тыс. строк9 0201 54032,3 МБ
Документы, три поля, все страницы12621127 КБ
Документы, $filter, 100 шт.1 0271503,5 МБ
Строки табличной части, 12 страниц3 13178210,2 МБ
Справочник, 2 страницы5121211,6 МБ
Записи регистра накопления, 109 страниц52 7409 341152 МБ
Записи регистра бухгалтерии, 135 страниц60 94210 506138 МБ
Turnovers()1861846 КБ
Balance() регистра бухгалтерии7941991,9 МБ
$apply groupby/aggregate213—338 Б
POST + PATCH + DELETE121——
$batch, 50 операций1 103—95 КБ
$metadata XML, первый / тёплый2 745 / 26402 / 4115,4 МБ
$metadata JSON, первый / тёплый2 582 / 23—4,7 МБ

Ступень 10 тыс. документов

Медиана, мс. «Страниц» — сколько ответов отдал OData4 при полном обходе.

ЗамерБез компонентыС компонентойstandard.odataСтраниц
Страница документов8 9481 49314 252 — всё одним ответом1
Документы целиком99 86416 88014 33511
Документы, три поля1 0252049811
Документы, $filter1 0272221491
Строки табличной части целиком38 90415 9505 359101
Строки табличной части, $expand1 8181 32823 388 — всё1
Справочник, $top=12527131
Справочник целиком4 7241 1191 06011
Справочник, три поля61621810211
Записи регистра накопления107 19424 69318 474198
Записи регистра бухгалтерии122 70934 80118 181225
Turnovers()2816201
Balance() регистра бухгалтерии7961991942
$apply115109—1
POST + PATCH + DELETE120126—1
$batch, 50 операций1 0981 168—1
$metadata XML, тёплый26254061

Ступень 100 тыс. документов

Лёгкие замеры — медиана после прогрева, тяжёлые обходы — один проход. standard.odata показан там, где его ответ разумного размера.

ЗамерБез компонентыС компонентойstandard.odataСтраницОбъём
Страница документов9 0881 450—132,3 МБ
Документы целиком992 314160 791—1013,5 ГБ
Документы, три поля10 4712 48093210110,5 МБ
Документы, $filter1 03822118213,5 МБ
Строки табличной части, $expand16 13515 487—12,3 МБ
Справочник, $top=12828141—
Справочник целиком47 85611 66310 689101153,5 МБ
Справочник, три поля6 3082 92397210113,9 МБ
Записи регистра накопления853 406471 346—1 0891,5 ГБ
Записи регистра бухгалтерии963 679637 858—1 1211,1 ГБ
Turnovers()2918191—
$apply groupby/aggregate1 0591 109—1—
Balance() регистра бухгалтерии78523019621,9 МБ
POST + PATCH + DELETE134129—1—
$batch, 50 операций1 0591 196—1—
$metadata XML / JSON, тёплый28 / 2528 / 2540215,4 МБ

Размер страницы и выдача одним ответом

Ступень 100 тыс., один проход, секунды. Выдача OData4 — компонентой.

НаборСтраницами по 1000По 5000Одним ответомstandard.odata
Документы с табличными частями, 3,5 ГБ161–199—229257–263
Справочник, 154 МБ12–201211,210,7
Записи регистра накопления, 1,5 ГБ493145134147
Записи регистра бухгалтерии, 1,1 ГБ636—199124

Объём ответа и память

ПоказательOData4standard.odata
Записи регистра накопления, 1,09 млн1,5 ГБ3,3 ГБ
Записи регистра бухгалтерии, 1,12 млн1,1 ГБ2,2 ГБ
Документы с табличными частями, 100 тыс.3,5 ГБ3,8 ГБ
Строки табличной части с $expand, 1 млнстраница 2,3 МБ3,7 ГБ одним куском
$metadata XML5,4 МБ8,5 МБ
$metadata JSON4,7 МБ—
Пик памяти Apache при ответе на 1,5–3,5 ГБ1,4–1,7 ГБ—

Куда уходит время внутри 1С

Разложение вызова на странице в 1000 записей, медиана, мс. Выдача — на языке 1С: видно, за что платит сервис без компоненты.

НаборВесь вызовЗапросВыгрузитьСтроки ТЧСериализацияОтвет
Документы, 44 тыс. строк ТЧ8 254311427–1 0027 81681
Записи регистра накопления38957—3763
Записи регистра бухгалтерии34057—3273
Справочник, 679 строк ТЧ395415203573
Документы, три поля8613—810

Ленивая модель и $metadata

Первый запрос нового сеанса на составе из 1 371 объекта и 2 203 наборов. «Память» — сколько держит сеанс.

Первый запрос нового сеансаПолная модельЛенивая модель
Один набор Catalog_Валюты1,6 с, 49,6 млн знаков0,17 с, 1,28 млн знаков
Набор с $expand49,6 млн знаков1,63 млн знаков
$metadata XML2,2 с, 54,4 млн знаков2,4 с, 6,0 млн знаков
$metadata, холодный, с кэшем между сеансами~2,7 с~0,55 с
$metadata, тёплый сеанс—26 мс

Запись и пакеты

Миллисекунды. Запись почти не зависит от объёма базы.

Операция1 тыс.10 тыс. без комп.10 тыс. с комп.100 тыс. без комп.100 тыс. с комп.
POST + PATCH + DELETE элемента справочника121120126134129
$batch, 50 операций GET1 1031 0981 1681 0591 196

Передача строк в компоненту

100 тыс. строк по 24 колонки. Выбор способа передачи и был главным решением: неудачный способ съедал весь выигрыш компоненты.

СпособУпаковка в 1СПередачаИтого
По одному значению4 931~8 30013 207
Строка с разделителями7 7471457 892
JSON, массив массивов——6 465
Внутренний формат таблицы значений, 81 млн знаков——1 316

Разбор тел запросов

Миллисекунды. Разбор занимает около 1 % времени $batch — ускорять там нечего.

ОперацийJSON batchmultipart/mixedТела записи
501144
1000757713

Как повторить

Стенд собирается из эталонной демобазы, генератор досыпает данные ступенями, прогон пишет итог в файл. Эталон и клоны при этом не меняются.

Прогон

devcli bench create   --name odata4bench --ref D:\1c-bases\odata4demo
devcli bench deploy   --name odata4bench
devcli bench generate --step 100000 --budget 5m
devcli bench run      --repeat 5                  # лёгкие замеры
devcli bench run      --repeat 0 --only "all|records"   # тяжёлые обходы
devcli bench breakdown --path Document_НачислениеЗарплаты --repeat 3