Рассмотрим распространенную ситуацию: сложная обработка или отчет в 1С:Предприятие 7.7, работающей на MS SQL Server, выполняется недопустимо долго, десятки минут. Первичная оптимизация кода — например, избавление от наиболее очевидных "тормозов" — дает лишь небольшое ускорение, после чего производительность будто упирается в невидимую стену. Иногда это проявляется в виде наблюдений о предельном количестве запросов к серверу в секунду, что наводит на мысль о неких внутренних ограничениях платформы.
На самом деле, предполагаемый лимит, например, в 1024 запроса в секунду, — это не жесткое ограничение платформы, а симптом неэффективного способа получения данных. Платформа 1С 7.7, выполняя множество мелких и неоптимальных запросов, просто достигает предела пропускной способности в связке "ODBC-драйвер – сеть – SQL Server". Корень проблемы не в платформе, а в подходе к написанию кода.
Проанализируем, как кардинально решить эту проблему и заставить отчеты "летать" за секунды, а не за минуты.
Это самый мощный и эффективный способ ускорения. Встроенный язык запросов 1С 7.7 имеет серьезные ограничения и часто генерирует не самый оптимальный T-SQL код. Основная проблема — это так называемая проблема "N+1 запроса", которая возникает при обходе данных в цикле с обращением к реквизитам через точку.
Пример неэффективного подхода:
Представим, что нам нужно в цикле обойти некий набор документов и для каждого документа получить название группы его контрагента. Код на встроенном языке 1С может выглядеть так:
// ... код получения выборки документов ...
Пока Выборка.ПолучитьДокумент() = 1 Цикл
// На каждой итерации этого цикла 1С генерирует
// ОТДЕЛЬНЫЙ запрос к SQL, чтобы получить контрагента,
// а затем еще один, чтобы получить его родителя (группу).
Сообщить(Выборка.Контрагент.Родитель.Наименование);
КонецЦикла;
Если в выборке 1000 документов, этот код сгенерирует более 1000 мелких запросов к SQL Server. Именно это и создает иллюзию "упора в лимит запросов в секунду".
Прямые запросы позволяют выполнить всю работу одним-единственным, но очень эффективным запросом на языке T-SQL. Для этого обычно используют внешние компоненты, самая известная из которых — 1С++.
Как это работает с прямыми запросами:
Подключаем компоненту 1С++ и создаем объект RecordSet.
Пишем запрос на T-SQL, который использует всю мощь SQL, в первую очередь — оператор JOIN для соединения таблиц. Наш запрос сразу свяжет таблицу документов, справочник контрагентов и справочник контрагентов еще раз (для получения родителя).
Выполняем запрос и обрабатываем результат. SQL Server выполнит один сложный запрос и вернет готовый набор данных, который мы просто обойдем в цикле уже без каких-либо обращений к базе.
Концептуальный пример на прямых запросах (с использованием 1С++):
// Создаем объект для выполнения прямого запроса
ЗапросSQL = СоздатьОбъект("AddIn.RecordSet");
// Текст запроса на чистом T-SQL.
// Названия таблиц и полей нужно смотреть в DDS-файле или через SQL Management Studio
ТекстЗапроса = "
|SELECT
| Контрагенты_Родитель.DESCR AS ИмяГруппыКонтрагента
|FROM
| _1SJOURN AS Журнал
| INNER JOIN DH1234 AS Документ ON Журнал.IDDOC = Документ.IDDOC
| INNER JOIN SC567 AS Контрагенты ON Документ.SP1235 = Контрагенты.ID
| INNER JOIN SC567 AS Контрагенты_Родитель ON Контрагенты.PARENTID = Контрагенты_Родитель.ID
|WHERE
| Журнал.DATE_TIME_IDDOC BETWEEN '20230101' AND '20231231'
|"; // Условия, таблицы и поля - примерные
// Выполняем ОДИН запрос к базе
Результат = ЗапросSQL.Open(ТекстЗапроса);
// Обрабатываем уже готовые данные без обращений к SQL
Пока Результат.EOF() = 0 Цикл
Сообщить(Результат.ИмяГруппыКонтрагента);
Результат.MoveNext();
КонецЦикла;
Результат.Close();
Преимущества очевидны: вместо тысяч запросов выполняется один. Это снижает нагрузку на сеть, на SQL Server и на сам клиент 1С. Скорость выполнения возрастает в десятки и даже сотни раз.
Для особо тяжелых отчетов, требующих сложных вычислений, агрегаций и многоступенчатой обработки, даже один прямой запрос может быть недостаточно быстрым. В таких случаях вычисления целесообразно перенести с клиента 1С непосредственно на сервер СУБД.
Для этого есть несколько инструментов:
Хранимые процедуры (Stored Procedures). Это заранее скомпилированный на сервере набор T-SQL команд. Из 1С мы можем вызвать такую процедуру, передать ей параметры (например, период отчета), а вся "магия" — создание временных таблиц, сложные соединения, расчеты — произойдет на стороне SQL Server с максимальной скоростью. Назад 1С получит уже готовый, финальный набор данных.
Представления (Views). Представление — это виртуальная таблица, основанная на результате запроса SELECT. Можно создать View, которое инкапсулирует сложную логику соединения таблиц. Для 1С (даже для прямого запроса) обращение к этому View будет выглядеть как обращение к простой таблице, что значительно упрощает код запросов.
Этот подход требует более глубоких знаний T-SQL, но для критически важных и ресурсоемких задач он незаменим.
Иногда проблему производительности можно решить, не углубляясь в прямые запросы, а изменив саму архитектуру хранения данных. Этот метод особенно хорош, когда отчет требует сложных вычислений "на лету" по большому объему данных.
Основная идея — предварительный расчет и хранение результатов.
Рассмотрим пример: отчет по продажам должен показывать себестоимость каждой проданной единицы товара, которая рассчитывается сложным алгоритмом на основе партий. Строить такой отчет "на лету" по большому периоду — очень долго.
Решение:
Создается дополнительный регистр или добавляется реквизит в табличную часть документа "Реализация товаров и услуг", например, `Себестоимость`.
В процедуру проведения документа добавляется код, который рассчитывает себестоимость в момент проведения и записывает готовый результат в этот новый реквизит/регистр.
Отчет теперь не выполняет никаких сложных вычислений. Он просто берет готовые данные из этого реквизита. Скорость его формирования возрастает многократно, так как сложный расчет заменяется простым чтением.
Да, это немного увеличивает время проведения документов и "раздувает" базу, но для отчетности это дает колоссальный выигрыш в производительности.
Даже с неоптимальным кодом можно добиться улучшения, если устранить узкое место в сетевой инфраструктуре. Когда клиент 1С находится на рабочей станции пользователя, а SQL Server — в серверной, каждый из тысяч мелких запросов проходит по сети, что создает значительные задержки.
Решение — использование терминального сервера (RDS/RDP).
Когда все пользователи работают с 1С в терминальной сессии на сервере, который находится в той же серверной (и в идеале в той же 10-гигабитной сети), что и SQL Server, сетевая задержка практически исчезает. Обмен данными между приложением 1С и базой данных становится почти мгновенным. Этот подход может дать значительное ускорение даже без изменения кода.
Итог: Не стоит искать мифические ограничения в DLL-библиотеках 1С. Проблема медленной работы 1С 7.7 на SQL почти всегда кроется в неэффективном коде, который порождает огромное количество мелких запросов. Переход на прямые запросы к SQL является главным и наиболее действенным решением, которое позволяет сократить время выполнения отчетов с десятков минут до нескольких секунд.