Как связать тяжелые SQL-запросы из Profiler с конкретным кодом и пользователем 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с производительностью крупной информационной системы на базе 1С часто требует погружения на уровень СУБД. Однако администраторы и разработчики часто сталкиваются с проблемой: SQL Profiler показывает «страшный» запрос с миллионами чтений, но совершенно непонятно, кто его запустил и какая обработка в 1С за это отвечает. В рамках данной статьи мы разберем комплексный подход к анализу таких ситуаций, используя как инструменты SQL Server, так и штатные механизмы платформы 1С.

Проблема анонимности запросов в SQL Profiler

Когда мы запускаем трассировку в SQL Profiler, мы видим события типа RPC:Completed или SQL:BatchCompleted. В колонках отображаются такие параметры, как Reads (логические чтения), CPU и Duration. Основная сложность заключается в том, что поле SPID (идентификатор процесса SQL) динамично: один и тот же сеанс 1С может использовать разные соединения с СУБД, а SPID может переиспользоваться разными пользователями через пул соединений.

Рассмотрим ситуацию: вы видите запрос, который выполнил 19 миллионов чтений (reads). Это не обязательно означает 19 миллионов строк в результате — это количество обращений к страницам данных размером 8 КБ в оперативной памяти или на диске. Чтобы понять, «откуда ноги растут», нам нужно связать этот запрос с контекстом исполнения в 1С.

Решение 1: Использование Технологического Журнала (ТЖ)

Это самый надежный способ. Технологический журнал позволяет записывать все события взаимодействия платформы с СУБД. Самое важное для нас — событие DBMSSQL. Рассмотрим, как это работает по шагам.

  1. Настроим сбор ТЖ на сервере приложений 1С. Нам нужно отлавливать длительные запросы. Создадим файл logcfg.xml с фильтром по длительности.
  2. Проанализируем полученные логи. В событии DBMSSQL платформа записывает текст SQL-запроса, который она отправила в СУБД, и — что критически важно — Context.
  3. Context — это цепочка вызовов процедур и функций 1С (стек вызовов), которая привела к выполнению этого запроса. Там будет указано имя пользователя, имя обработки и даже номер строки кода.

Сравнивая текст запроса из Profiler с текстом из ТЖ, мы получаем полную картину. Текст запроса в ТЖ обычно содержит идентификаторы таблиц (например, _Reference50), которые легко сопоставить с данными из SQL Profiler.

Решение 2: Сопоставление через консоль кластера 1С

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

В SQL Profiler или через системное представление sys.dm_exec_requests находим SPID активного тяжелого запроса. Далее открываем Консоль администрирования кластера 1С. Переходим в раздел «Сеансы». Нам нужно добавить колонку «Номер соединения с СУБД». Значение в этой колонке и есть наш SPID. Таким образом, мы мгновенно видим имя пользователя и компьютер, с которого инициирована нагрузка.

Решение 3: Расшифровка имен таблиц СУБД

SQL-сервер оперирует именами вроде _InfoRg12345 или _Document50. Чтобы понять, что это за объект в терминах 1С, используем встроенную функцию платформы. Рассмотрим пример кода, который выгружает структуру базы данных в таблицу:


СтруктураБД = ПолучитьСтруктуруХраненияБазыДанных();
Для Каждого СтрокаСтруктуры Из СтруктураБД Цикл
    Если СтрокаСтруктуры.ИмяТаблицыХранения = "_Reference50" Тогда
        Сообщить("Это справочник: " + СтрокаСтруктуры.ИмяМетаданных);
    КонецЕсли;
КонецЦикла;

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

Решение 4: Переход от Profiler к Extended Events (XEvents)

Современные версии SQL Server рекомендуют использовать Extended Events вместо Profiler. Это создает значительно меньшую нагрузку на сервер. Проанализируем преимущества этого метода:

Решение 5: Динамические административные представления (DMV)

Если вы пропустили момент выполнения запроса и Profiler не был включен, ситуацию можно спасти, обратившись к кэшу планов SQL-сервера. Рассмотрим запрос к системным представлениям, который выведет топ самых «читающих» запросов:


SELECT TOP 20
    st.text AS [Query Text],
    qs.total_logical_reads AS [Total Reads],
    qs.max_logical_reads AS [Max Reads],
    qs.execution_count AS [Execution Count],
    qp.query_plan AS [Query Plan]
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp
ORDER BY qs.total_logical_reads DESC;

Этот метод позволяет найти тот самый запрос на 19 миллионов чтений, даже если он выполнялся час назад, и детально изучить его план выполнения.

Выясним причины высокой нагрузки

Почему 1С генерирует такие тяжелые запросы? Выделим три основные причины:

  1. Неоптимальные соединения: Соединение виртуальных таблиц (Остатки, Срезы последних) без предварительной выгрузки во временные таблицы. SQL-серверу приходится строить огромные промежуточные декартовы произведения.
  2. Механизм RLS (Record Level Security): Когда включена проверка прав на уровне записей, 1С дописывает к вашему простому запросу огромный кусок кода с проверками. Это часто приводит к полному сканированию таблиц (Table Scan).
  3. Отсутствие индексов: Поиск в 1С по реквизиту, у которого не стоит галочка «Индексировать», заставляет СУБД перебирать все записи в таблице.

Подведем итог: для эффективного решения задачи анализа запросов недостаточно одного Profiler. Нужно использовать связку: SQL Profiler (или XEvents) + Технологический Журнал 1С + Консоль кластера. Только сопоставление данных из всех этих источников позволит точно определить «виновника» тормозов и оптимизировать конкретную строку кода 1С.

← На главную