В процессе администрирования крупной базы данных на платформе 1С Предприятие администраторы СУБД (MS SQL Server, PostgreSQL) часто сталкиваются с запросами, которые вызывают критическую нагрузку на процессор или дисковую подсистему. Мы видим «монструозный» SQL-текст, выполняющийся несколько минут, но как понять, какая именно строчка кода в конфигурации 1С породила этот кошмар?
Сложность заключается в том, что платформа 1С транслирует запросы со своего внутреннего объектного языка SDBL в запросы СУБД, заменяя понятные имена метаданных (например, РегистрНакопления.Продажи) на физические имена таблиц (например, _AccumReg123). В этой статье мы подробно разберем несколько профессиональных методик, которые помогут вам сопоставить тяжелый SQL-запрос с конкретной строкой кода 1С.
Если перед вами текст SQL-запроса с именами таблиц вида _Reference45 или _Document220, первым делом необходимо сопоставить их с реальными объектами конфигурации 1С. Для этого мы можем использовать штатный механизм платформы.
Рассмотрим встроенную функцию ПолучитьСтруктуруХраненияБазыДанных(). Она возвращает полную таблицу соответствий физических таблиц СУБД и объектов метаданных 1С. Напишем простую обработку, которая поможет нам быстро найти виновника:
ТаблицаСтруктуры = ПолучитьСтруктуруХраненияБазыДанных();
ИскомаяТаблицаСУБД = "_InfoRg134"; // Укажите имя таблицы из SQL-запроса
Для Каждого СтрокаСтруктуры Из ТаблицаСтруктуры Цикл
Если СтрокаСтруктуры.ИмяТаблицыХранения = ИскомаяТаблицаСУБД Тогда
Сообщить("Найдено соответствие:");
Сообщить("Объект 1С: " + СтрокаСтруктуры.ИмяТаблицы);
Сообщить("Тип метаданных: " + СтрокаСтруктуры.Метаданные);
КонецЕсли;
КонецЦикла;
После того как мы выяснили, какие объекты 1С задействованы в СУБД-запросе, мы можем запустить глобальный поиск по конфигурации (комбинация клавиш Ctrl + Shift + F), используя имена найденных объектов (например, РегистрСведений.ЦеныНоменклатуры). Чтобы сузить область поиска, ищите места совместного соединения этих таблиц.
Этот способ является самым надежным и точным, так как он позволяет получить не просто имя объекта 1С, а точный стек вызовов (контекст) встроенного языка вплоть до номера строки в модуле, где был вызван метод Выполнить().
Разберем по шагам, как настроить сбор логов для локализации конкретного запроса:
logcfg.xml (он должен находиться в каталоге C:\Program Files\1cv8\conf\ для Windows-сервера).DBMSSQL для MS SQL Server или DBPOSTGRS для PostgreSQL).Применим следующий шаблон конфигурации logcfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-journal">
<log location="C:\v8logs\heavy_queries" history="2">
<event>
<eq property="Name" value="DBMSSQL"/>
<like property="Sql" value="%Reference12%"/>
<like property="Sql" value="%InfoRg134%"/>
<like property="Sql" value="%Document254%"/>
</event>
<property name="all"/>
</log>
</config>
Проанализируем работу этого фильтра. Как только платформа 1С выполнит запрос к СУБД, в котором одновременно будут задействованы таблицы справочника 12, регистра сведений 134 и документа 254, данное событие запишется в лог. В логе нас будет интересовать свойство Context. Оно выглядит примерно так:
Context=ОбщийМодуль.ПроведениеСервер.Модуль : 124 : ДокументОбъект.ВыполнитьЗапрос()
Это дает нам стопроцентное понимание того, где именно в конфигурации находится проблемный код.
Что делать, если тяжелый запрос выполняется прямо сейчас и "вешает" рабочую базу, а времени на настройку технологического журнала нет? Выясним причину на лету с помощью СУБД и консоли администрирования 1С:
SELECT r.session_id, r.status, r.cpu_time, r.total_elapsed_time, t.text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.session_id > 50;
session_id (это уникальный идентификатор сессии в СУБД, также известный как SPID).session_id.Таким образом, вы мгновенно определите, какой именно пользователь запустил этот запрос, какой компьютер он использует и какое приложение (например, фоновое задание или конкретный отчет) сейчас перегружает систему.
Проанализируем ситуации, при которых сопоставление может вызвать трудности, и выделим важные правила:
#tt1, #tt2 или физических таблиц типа _t_temp, это означает использование временных таблиц. Искать в 1С нужно пакетный запрос с использованием конструкции ПОМЕСТИТЬ.ТекстЗапроса = ТекстЗапроса + "ГДЕ..."), обычный глобальный поиск по тексту запроса может не сработать. В этом случае единственным решением будет сбор логов Технологического журнала с включенным свойством Context, как описано в Меоде 2.Используя предложенные методы совместно, вы сможете оперативно локализовать любые проблемные запросы и оптимизировать работу вашей системы 1С.