Как программно посчитать количество выполнений запроса в 1С и передать контекст между процедурами?

Программист IT и автоматизация бизнеса
← На главную

Часто при разработке конфигураций возникает специфическая задача: необходимо программно определить, сколько раз выполнился конкретный запрос, или просто зафиксировать сам факт его выполнения. Проанализируем ситуацию, с которой столкнулся автор темы: в одной процедуре выполняется запрос, а в другой процедуре необходимо вывести пользователю сообщение, если этот запрос действительно отработал. Разберем по шагам, как правильно подойти к решению этой задачи, избежав типичных ошибок.

Базовый подход: использование локальных счетчиков и флагов

Если задача заключается только в том, чтобы зафиксировать выполнение кода внутри конкретного контекста, не нужно усложнять систему и обращаться к базе данных. Рассмотрим простейший и самый надежный вариант — использование числовой переменной или переменной с типом Булево.

Если нам нужно посчитать количество итераций, мы можем объявить переменную перед циклом или вызовом и наращивать ее. Посмотрим на пример кода:


КоличествоВыполненийЗапроса = 0;

// Какой-то цикл или условие
КоличествоВыполненийЗапроса = КоличествоВыполненийЗапроса + 1;
Запрос.Выполнить();

Если же нам достаточно знать лишь факт выполнения (было или не было), используем логический флаг. Разберем этот вариант:


ЗапросВыполнен = Ложь;

Запрос.Выполнить();
ЗапросВыполнен = Истина;

Если ЗапросВыполнен Тогда
    // Вывод сообщения или другая логика
КонецЕсли;

Решение архитектурной проблемы: передача состояния между процедурами

Выясним истинную причину затруднений: часто код разделен на разные процедуры (например, одна готовит данные, другая формирует интерфейсные сообщения). Использование глобальных объектов базы данных (констант, регистров сведений) для хранения таких временных флагов — плохая практика. Это приведет к проблемам с блокировками, если в базе параллельно работает несколько пользователей.

Рассмотрим правильные архитектурные паттерны передачи состояния в 1С:

  1. Передача через параметры (Структуры). Изменим сигнатуру вызываемой процедуры так, чтобы она возвращала служебную информацию. Упакуем результат в объект Структура. Первая процедура вернет структуру с данными и флагом, а вторая прочитает это свойство.
  2. Переменные модуля. Если обе процедуры находятся в одном программном модуле (например, в модуле формы), мы можем объявить переменную на уровне модуля с помощью инструкции Перем в самом начале кода. Эта переменная сохранит свое значение между вызовами процедур в рамках жизни данного объекта.
  3. Временное хранилище. Если процедуры разорваны по контексту (например, запрос выполняется на сервере, а сообщение нужно вывести на клиенте сильно позже), воспользуемся функцией ПоместитьВоВременноеХранилище(). Это сохранит наш флаг в оперативной памяти сервера с привязкой к идентификатору формы, избегая записи в БД.
  4. Параметры сеанса. Если нужно отслеживать события глобально для текущего пользователя (и не писать это в базу), создадим параметр сеанса. Он хранится в памяти кластера серверов, читается очень быстро и не вызывает коллизий.

Глобальный подсчет и логирование запросов

Если задача все-таки носит административный или отладочный характер (например, мы хотим узнать, как часто пользователи вызывают тяжелый запрос), локальных переменных будет недостаточно. Разберем инструменты платформы 1С для таких задач.

Журнал регистрации
Мы можем добавить программную запись в журнал регистрации непосредственно после выполнения запроса. Это не блокирует таблицы базы данных и позволяет позже проанализировать логи.


Запрос.Выполнить();
ЗаписьЖурналаРегистрации("АнализПроизводительности", 
    УровеньЖурналаРегистрации.Информация, 
    , 
    , 
    "СчетчикЗапросов: Выполнен тяжелый запрос");

Технологический журнал (ТЖ)
Это самый профильный и точный инструмент платформы. Настроив файл конфигурации ТЖ (logcfg.xml), мы заставим платформу собирать события SDBL (запросы на внутреннем языке 1С) или DBMSSQL (транслированные запросы к СУБД). ТЖ позволяет отследить контекст, пользователя и точное время выполнения без изменения исходного кода конфигурации.

Оптимизация: кэширование вместо подсчета

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

Мы можем вынести этот запрос в отдельный общий модуль и в свойствах модуля установить Повторное использование возвращаемых значений (на время вызова или на время сеанса). При первом обращении 1С выполнит запрос к СУБД, а при всех последующих вызовах из любых процедур — просто вернет готовый результат из оперативной памяти. Это элегантно решает проблему избыточных чтений без необходимости вручную внедрять счетчики в код.

← На главную