При анализе производительности запросов 1С в SQL Server Profiler разработчики часто сталкиваются с проблемой: временные таблицы в SQL именуются платформой как #tt1, #tt2, #tt99 и так далее. Эти имена меняются динамически в зависимости от количества таблиц в пакете, версии платформы и даже порядка выполнения. Прямое сопоставление имени из кода 1С (например, МенеджерВременныхТаблиц.ТаблицаТоваров) с именем в SQL становится нетривиальной задачей, особенно в сложных запросах с десятками пакетов. В этой статье мы разберем несколько эффективных методов идентификации этих таблиц.
Самый простой и быстрый способ, не требующий глубоких знаний SQL или настройки сервера, — это добавление в текст запроса уникальной константы. Разберем, как это работает. В SQL Server Profiler в колонке TextData отображается полный текст выполняемого запроса. Если мы добавим в пакет запроса фиктивное поле с уникальной строкой, мы сможем легко найти это место в трассировке.
Рассмотрим пример. Допустим, нам нужно найти создание временной таблицы ВТ_ДанныеПродаж. Мы можем модифицировать запрос следующим образом:
Запрос.Текст =
"ВЫБРАТЬ
| ""МОЯ_МЕТКА_ПРОДАЖИ"" КАК Метка,
| Продажи.Номенклатура,
| Продажи.Количество
|ПОМЕСТИТЬ ВТ_ДанныеПродаж
|ИЗ
| РегистрНакопления.Продажи КАК Продажи";
Проанализируем ситуацию: в Profiler мы ищем строку "МОЯ_МЕТКА_ПРОДАЖИ". Как только мы находим оператор SELECT INTO #tt..., содержащий эту строку, мы точно знаем, что данная таблица #tt и есть наша ВТ_ДанныеПродаж. Этот метод хорош тем, что требует минимальных правок кода, однако он не всегда удобен, если вы работаете с типовыми механизмами, которые нельзя менять.
Если запрос очень большой и меток недостаточно, или вам нужно остановить выполнение на конкретной таблице, можно использовать объект СхемаЗапроса. Этот метод позволяет разбить один большой пакетный запрос на отдельные части и выполнять их по очереди в цикле отладки.
Выясним причину удобства этого способа: вы можете программно отловить момент создания конкретной временной таблицы. Рассмотрим пример кода, который можно запустить в отладчике или внешней обработке:
Процедура ИдентифицироватьВТ(Запрос)
// Запрос - исходный запрос с текстом и параметрами
Схема = Новый СхемаЗапроса;
Схема.УстановитьТекстЗапроса(Запрос.Текст);
// Создаем временный запрос для пошагового выполнения
ПошаговыйЗапрос = Новый Запрос;
Для каждого Параметр Из Запрос.Параметры Цикл
ПошаговыйЗапрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
ПошаговыйЗапрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Перебираем пакеты
Для каждого Пакет Из Схема.ПакетЗапросов Цикл
Если ТипЗнч(Пакет) = Тип("ЗапросВыбораСхемыЗапроса") Тогда
ТекстЭтапа = Пакет.ПолучитьТекстЗапроса();
ИмяВТ = Пакет.ТаблицаДляПомещения;
ИначеЕсли ТипЗнч(Пакет) = Тип("ЗапросУничтоженияТаблицыСхемыЗапроса") Тогда
ТекстЭтапа = "УНИЧТОЖИТЬ " + Пакет.ИмяТаблицы;
ИмяВТ = "";
КонецЕсли;
// Здесь мы можем поймать конкретную таблицу
Если ИмяВТ = "НужнаяМнеТаблица" Тогда
// Точка останова: сейчас в Profiler появится запрос на создание этой ВТ
ПошаговыйЗапрос.Текст = ТекстЭтапа;
ПошаговыйЗапрос.Выполнить();
Иначе
ПошаговыйЗапрос.Текст = ТекстЭтапа;
ПошаговыйЗапрос.Выполнить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Используя этот подход, мы выполняем каждый пакет отдельно. В Profiler мы увидим последовательные запросы, и тот, который выполнится в момент нашей точки останова по имени ИмяВТ, и будет искомым.
Для профессиональной отладки на сервере, где нельзя запускать конфигуратор, лучшим способом является настройка Технологического Журнала. Платформа 1С при записи событий СУБД (событие DBMSSQL) сохраняет сопоставление метаданных 1С и SQL-объектов.
Разберем по шагам, как это настроить:
logcfg.xml в каталоге настроек 1С.DBMSSQL с фильтром по вашему процессу или базе данных.Context, чтобы видеть строку кода 1С, и sql для самого текста запроса.В логах ТЖ вы увидите записи, где перед SQL-кодом CREATE TABLE #tt... будет указан контекст выполнения (имя процедуры, строка кода) и часто — комментарии платформы, указывающие на структуру временной таблицы. Это самый надежный метод "посмертного" анализа, когда проблема уже произошла, а трассировка Profiler осталась.
Если у вас уже запущен Profiler и вы видите несколько вставок в разные #tt, проанализируйте колонку Rows (или RowCounts). Посмотрим на ситуацию: вы знаете, что во временную таблицу ВТ_Остатки должно попасть ровно 150 записей. В Profiler ищите оператор INSERT INTO #tt..., у которого значение в колонке Rows равно 150.
Также можно выполнить оперативный запрос к системным представлениям tempdb, пока сессия 1С еще активна:
SELECT
t.name AS TableName,
c.name AS ColumnName,
c.column_id
FROM tempdb.sys.columns c
JOIN tempdb.sys.tables t ON c.object_id = t.object_id
WHERE t.name LIKE '#tt%'
ORDER BY t.name, c.column_id;
Сравнив набор колонок и их типы в SQL с описанием временной таблицы в 1С (через Метаданные или Выгрузить()), вы сможете однозначно сопоставить #tt99 с вашим объектом.
Не забывайте про самый очевидный, но рабочий метод: порядок таблиц в SQL-трассировке обычно строго соответствует порядку их появления в тексте запроса 1С. Если ваша ВТ_Вторая создается после ВТ_Первая, то и в Profiler соответствующий #tt с большим порядковым номером или более поздним временем выполнения будет относиться ко второй таблице.
Важный момент: Платформа 8.3 в последних релизах часто добавляет технические комментарии в начало SQL-запроса. Всегда внимательно изучайте начало блока TextData в Profiler — там может содержаться идентификатор запроса, который поможет сузить область поиска.
Для быстрой отладки используйте текстовые метки (Метод 1). Если нужно детально изучить сложный алгоритм — применяйте СхемуЗапроса (Метод 2). В случае расследования проблем на продуктивной базе используйте Технологический журнал (Метод 3). Сочетание этих подходов позволит вам мгновенно ориентироваться в логах SQL-сервера.