Постановка задачи: получать данные о заказах из базы данных 1С: Предприятие в формате JSON для отображения на сайте. Запросы должны обрабатываться максимально быстро, по возможности, не мешать работе пользователей в базе.

Задача, конечно, надуманная, но хорошо отражает целый класс задач из реального мира – обслуживание большого количества мелких запросов на чтение данных. Обработка с максимальной скоростью, потому что никто не любит, когда сайт тормозит. И поисковые роботы тоже. Они за такое могут понизить сайт в выдаче результатов. При этом локальные пользователи тоже должны как-то работать в базе, проводить документы, формировать отчёты.

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

Хост (он же будет выступать клиентом):

  • Intel(R) Core(TM) i7-7500U CPU @ 2.90 GHz, RAM 16 ГБ

  • Windows 11 Pro 22H2

  • Apache JMeter 5.6.3

  • Oracle VM VirtualBox 7.0.14

Виртуальная машина (сервер):

  • 2 процессора, 6 ГБ оперативной памяти

  • Windows Server 2022 Standard 21H2

  • SQL Server 2022

  • Платформа 1С, 8.3.24.1467

  • 1С: Управление Торговлей, 11.5.16.97

  • Kraxe 0.3.3

Рассмотрим 2 варианта решения – использование встроенных в платформу HTTP-сервисов с публикацией на IIS и прямое чтение данных из SQL. Первый вариант реализуем как расширение для конфигурации. Для второго используем Кракен  – веб-сервер для MS SQL.

Расширение для конфигурации

Сначала подготовим небольшое расширение конфигурации 1С, в котором реализован HTTP-сервис. Сервис получает в качестве параметра номер заказа. По номеру находит документ и возвращает этот номер с датой и статусом. В запросе учтём, что в базе могут быть заказы с одинаковым номером. Для простоты будем возвращать данные самого позднего из заказов.

Расширение для конфигурации 1С
Конфигуратор 1С: Предприятие
Конфигуратор 1С: Предприятие

Конфигурацию публикуем на IIS с настройками по умолчанию. Важный момент для анализа производительности - отладка на сервере 1C отключена.

В демонстрационной базе из комплекта поставки есть полсотни документов «Заказ клиента». В большинстве из них поля НомерПоДаннымКлиента и ДатаПоДаннымКлеинта пустые. Заполним номер значениями от 01 до 58, а дату – датой документа. В процессе теста будем запрашивать не один документ, а произвольный из этого диапазона.

Открываем из браузера на клиенте адрес публикации:
http://192.168.100.10/trade_11/hs/dds/order?Id=33

Всё в порядке, данные сервис отдаёт. Теперь можно настраивать второй вариант – прямые запросы в SQL.

Настройка Кракена

Бесплатная версия Кракена имеет некоторые ограничения – не более 100 строк в результате запроса, но для тестов и многих реальных задач вполне годится. Качаем, распаковываем, устанавливаем как службу:

c:\kraxe>kraxe.exe -install

Настройки сервера хранятся в файле kraxe.conf. Открываем его и внесём некоторые изменения.

kraxe.conf
Настройки Кракена
Настройки Кракена

Сначала в разделе http_server нужно указать IP-адрес и порт, на которых сервер будет принимать входящие запросы. Порт, чтобы не мешать IIS с опубликованной 1С, укажем 8080. По умолчанию, этот порт закрыт файрволом. Запускаем firewall.cpl, добавляем правило, разрешающее входящие запросы по этому порту.

В том же файле формируется список пользователей сервиса. Удалим запись, разрешающую анонимную аутентификацию. Оставим одну запись для пользователя Admin.

В разделе sql_server зададим параметры подключения к SQL Server. Кракен подключается к SQL Server по протоколу TCP. Убедимся, что этот протокол включен в настройках SQL сервера.

SQL Server Configuration Manager
Настройки SQL Server
Настройки SQL Server

Вернемся к настройкам Кракена. Имя БД, логин, пароль – тут всё очевидно.

Параметр pool_size – максимальное количество одновременных подключений к SQL серверу, которые может открыть и поддерживать Кракен. Забегая вперед, отмечу, что увеличение этого параметра в моём тесте никак не повлияло на скорость обработки запросов. Вероятно, если запросы будут сложнее и скорость их обработки на стороне SQL будет меньше, тогда понадобится несколько подключений, чтобы уменьшить очередь.

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

В разделе bindings опишем только один ресурс – “/order”. Этот ресурс будет связан с файлом ./queries/order.sql. У запроса будет один параметр с типом число (I16) и значением по умолчанию равным 0. При обращении к ресурсу /order?Id=33, в SQL запросе будет установлено значение переменной @ID = 33.

Раздел parameters из файла настроек удалим. Он нам пока не понадобится.

Теперь нужен файл с запросом, который получает данные заказа клиента по его номеру. Запустим SQL Server Profiler. Выполняем запрос из браузера к HTTP-сервису, который настроили ранее и найдём похожий на наш запрос:

exec sp_executesql N'SELECT TOP 1
T1._Fld10563,
T1._Fld10564,
T1._Fld10547RRef,
T1._IDRRef
FROM dbo._Document1092 T1
WHERE ((T1._Fld3035 = @P1)) AND ((T1._Fld10563 = @P2))
ORDER BY (T1._IDRRef) DESC',N'@P1 numeric(10),@P2 nvarchar(4000)',0,N'33'

Чтобы сопоставить имена таблиц из запроса с данными 1С: Предприятия нужно получить структуру хранения данных в БД. Готовых обработок для 1С много. Например, «Структура хранения данных».

Действительно, таблица _Document1092 – это документы Заказ клиента. Поле _Fld10563 – НомерПоДаннымКлиента, _Fld10564 – ДатаПоДаннымКлиента, _Fld10547RRef – Статус, а _Fld3035 – ОбластьДанныхОсновныеДанные.

Перепишем запрос. Разделение данных по областям у нас не используется, поэтому одно условие из запроса можно исключить. Если для документов, которые выбираются запросом в 1С включено версионирование, тогда в запросе необходимо учитывать поле _Version. Там будет timestamp, по которому можно отсортировать версии одного документа. В нашем случае это тоже не актуально.

Перечисления в БД 1С хранятся особым образом (подробнее об этом написано здесь). Для сопоставления идентификаторов перечислений с их представлениями необходимо выгрузить конфигурацию в xml файлы (из конфигуратора).

Открываем файл ..\Enums\СтатусыЗаказовКлиентов.xml

СтатусыЗаказовКлиентов.xml
Идентификаторы и имена значений перечислений
Идентификаторы и имена значений перечислений

Внимательнее! Идентификаторы в выгрузке имеют другой порядок байтов.

Теперь можем написать запрос и сохранить его в файл ./queries/order.sql

SELECT TOP 1
  T1._Fld10563 as Id,
  T1._Fld10564 as Date,
  CASE T1._Fld10547RRef
    WHEN 0xa1675473ecec326649b4b85516d451ca THEN 'НеСогласован'
    WHEN 0xb58f438fd9fb9fcb4711d9e217f46797 THEN 'КОбеспечению'
    WHEN 0xb2d15805b9177e7845e991dfb027cbd4 THEN 'КОтгрузке'
    WHEN 0xb0e8c70f8e9e2b96440ba5356e7c22c2 THEN 'Закрыт'
  END as Status
FROM dbo._Document1092 as T1
WHERE T1._Fld10563 = @ID
ORDER BY T1._IDRRef DESC

Адрес второго сервиса для тестирования прямых запросов получился такой:
http://192.168.100.10:8080/order?Id=33

Запускаем службу Kraxe и переходим к тестам.

Тестирование производительности

Для тестирования на клиенте настроил Apache JMeter: 100 потоков запускаются в течении 100 секунд и каждый из них отправляет 10 запросов.

Thread Group
Настройка потоков запросов
Настройка потоков запросов

Каждый запрос случайным образом выбирает номер заказа от 1 до 58 и подставляет в URL.

Random Variable
Случайное значение переменной для запроса
Случайное значение переменной для запроса

Для каждого сервиса выполним по 5 циклов. Для анализа самыми важными будут 3 показателя: среднее время обработки запроса, медианное время, отклонение от среднего времени (разброс значений).

Результаты:

 

Среднее время, мс

Медианное время, мс

Отклонение, мс

1С: Предприятие + IIS

1

38

28

138

2

27

26

7

3

25

25

6

4

41

40

16

5

40

39

16

 

34.2

31.6

36.6

SQL + Kraxe

1

12

11

8

2

19

15

14

3

11

10

8

4

11

10

5

5

16

11

18

 

13.8

11.4

10.6

Выводы

Тест без сомнений синтетический. Никак не учтена параллельная работа пользователей в БД, разные профили нагрузки для разных баз. Ну, разве что фоновые задания остались включенными на сервере 1С. Но в целом, порядок цифр и тенденция очевидны. Использование прямых запросов позволяет увеличить скорость получения данных из базы данных в 2-3 раза, повысить отзывчивость сайта.

Отмечу серьёзные недостатки прямого получения данных:

  1. Сложность разработки. Встроенный в платформу HTTP-сервис пишется за полчаса и помещается целиком на один экран. Для подготовки текста SQL запроса нужно выяснить структуру таблиц БД, хорошо понимать особенности хранения данных (например, перечисления). Полученное решение прибито гвоздями к конкретной БД, потому что имена таблиц для аналогичной конфигурации в другой БД будут отличаться.

  2. Сложность поддержания решения в рабочем состоянии. В процессе доработки и обновления конфигурации имена таблиц и полей в таблицах могут изменяться. Это нужно учитывать и отслеживать.

  3. Фирма 1С считает прямой доступ к БД нарушением лицензионного соглашения.

Решение по использованию прямых запросов к БД должно приниматься с учётом этих недостатков. Если можно обойтись штатными средствами – делайте средствами платформы.

Комментарии (5)


  1. anonymous
    28.04.2024 17:30

    НЛО прилетело и опубликовало эту надпись здесь


    1. vis_inet
      28.04.2024 17:30

      В каком смысле?

      Уже вышло - автор протестировал то, что хотел.


  1. mixsture
    28.04.2024 17:30
    +2

    Отмечу серьёзные недостатки прямого получения данных:

    вы забыли еще про блокировки, которые существуют в пространстве сервера приложений. Вы их обходите, а значит получаете грязное чтение.

    Зачем вам в запросе упорядочивание? Думаю, оно не несет никакой нагрузки и его можно убрать.

    Обработка с максимальной скоростью, потому что никто не любит, когда сайт тормозит.

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


    1. Kuzmin_R Автор
      28.04.2024 17:30
      +1

      Упорядочивание нужно для того, чтобы получить последний документ с указанным в отборе номером. В БД может быть несколько документов с одинаковым номером, например, за разные годы.

      С доставкой изменений полностью согласен - это гораздо лучшее решение. Рассмотренная ситуация - это только упрощённый пример. Суть исследования в том, чтобы понять, насколько прямой доступ даст ускорение.

      Грязное чтение возможно, но оно далеко не всегда будет проблемой.


      1. mixsture
        28.04.2024 17:30

        Упорядочивание нужно для того, чтобы получить последний документ с указанным в отборе номером. В БД может быть несколько документов с одинаковым номером, например, за разные годы.

        Тогда бы было упорядочивание по дате, а у вас по idref (16 байтный UUID) - полагаться на него, что он будет выдавать возрастающие строки с течением времени нельзя (а еще направление сотировки - обратное - убывание desc). Я бы в принципе выкинул отсюда упорядочивание как довольно затратную процедуру, ограничившись диапазоном дат (вроде "полгода назад максимум").