Диагностика медленных запросов в 1С 8.3

· 9 мин

Содержание

Проверка запросов в 1С 8.3 идёт по цепочке: замером производительности и технологическим журналом находят медленный вызов, его текст и план разбирают в консоли запросов и на стороне SQL Server, после — ищут блокировки и правят индексы. На эти четыре шага сводится почти любая диагностика производительности.

Браться за оптимизацию вслепую бессмысленно. Сначала нужны цифры: какой запрос выполняется дольше всех, сколько раз в минуту он вызывается и чего он ждёт — процессор, диск или снятия блокировки. Ниже — инструменты, которые эти цифры дают, и типовые приёмы, которыми потом правят код.

Консоль запросов: смотрим текст, результат и время

Консоль запросов — типовая внешняя обработка (входит в комплект ИТС и в набор «Инструменты разработчика»). Она открывает текст запроса, выполняет его на боевых данных и показывает результат с временем выполнения. Это первый инструмент, когда запрос уже известен и нужно понять, что он возвращает и как долго.

Чтобы открыть обработку в режиме «1С:Предприятие»: Главное меню → Файл → Открыть, выберите файл .epf. Потребуется право на открытие внешних обработок.

В консоли удобно:

  • 📝 вставить текст запроса и выполнить его, не трогая конфигурацию;
  • ⏱ увидеть длительность выполнения прямо под кнопкой «Выполнить»;
  • 🔧 собрать запрос через встроенный конструктор, если текста ещё нет;
  • 🧩 подставить параметры и прогнать запрос с теми же значениями, что и в проблемной операции.

Для запросов внутри конфигурации есть и штатный путь: в конфигураторе откройте модуль, установите курсор в строку запроса и вызовите Конструктор запроса из контекстного меню. Он же показывает, какие таблицы и соединения реально участвуют.

Консоль показывает, что запрос делает и сколько это длится. Почему он медленный на стороне СУБД — видно уже в технологическом журнале и в плане SQL.

Замер производительности: находим самый долгий вызов

Когда непонятно, какой именно запрос тормозит проведение или открытие формы, запускают замер производительности. Делается это из конфигуратора: меню Отладка → Замер производительности. После старта выполните проблемное действие в пользовательском режиме и остановите замер.

Результат — список строк кода с суммарным временем и числом вызовов. Сортировка по времени сразу выводит наверх «горячие» участки: как правило, это запрос в цикле или тяжёлое соединение.

Параллельно смотрят на APDEX — интегральную оценку отклика ключевых операций. Если он просел по конкретной операции, замер производительности покажет, в какой именно строке кода уходит время.

Технологический журнал: ловим долгие запросы к СУБД

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

Журнал настраивается файлом logcfg.xml в каталоге conf платформы (путь вида C:\Program Files\1cv8\conf). Вот конфигурация, которая пишет только запросы к СУБД длительностью примерно от трёх секунд:

<config xmlns="http://v8.1c.ru/v8/tech-log">
  <log location="C:\logs\tj" history="24">
    <event>
      <eq property="name" value="DBMSSQL"/>
      <ge property="duration" value="3000000"/>
    </event>
    <property name="all"/>
  </log>
</config>

Здесь важны два свойства:

  • name="DBMSSQL" — события запросов к серверу СУБД (текст в Sql). Событие SDBL — тот же запрос на языке запросов 1С, его удобно сопоставлять с кодом.
  • duration — порог длительности в микросекундах (3000000 ≈ 3 секунды). Порог подбирают так, чтобы в лог попадали именно проблемные запросы, а не весь поток.

После записи журнала файлы из каталога location разбирают: ищут самые долгие события DBMSSQL, по planSQLText смотрят план выполнения, по Context — из какого места конфигурации пришёл запрос.

Включённый технологический журнал пишет на диск непрерывно и сам по себе нагружает систему. Ставьте узкий фильтр, короткое окно (history в часах) и не забывайте удалять logcfg.xml после диагностики — иначе лог быстро забьёт диск.

Поиск и разбор блокировок

Если операция «висит», но процессор и диск свободны — почти наверняка дело в блокировках. Сеанс ждёт, пока другой сеанс освободит данные. В управляемом режиме блокировок это ловят тем же технологическим журналом по трём событиям:

  • TLOCK — установка и снятие управляемых блокировок;
  • TTIMEOUT — сеанс не дождался блокировки за отведённое время (та самая ошибка «Превышено время ожидания предоставления блокировки»);
  • TDEADLOCK — взаимоблокировка: два сеанса ждут данные друг друга.

По паре TTIMEOUT/TDEADLOCK видно, какой ресурс не поделили и какие сеансы в этом участвовали. Дальше смотрят, можно ли сократить длительность транзакции: вынести запросы из транзакции, уменьшить объём читаемых данных, упорядочить запись документов в едином порядке.

На стороне SQL Server текущие блокировки видно через системные представления:

SELECT
    r.session_id          AS сеанс,
    r.blocking_session_id AS кто_блокирует,
    r.wait_type,
    r.wait_time,
    t.text
FROM sys.dm_exec_requests AS r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
WHERE r.blocking_session_id <> 0;

Непустой blocking_session_id — это и есть цепочка ожидания. Для разового взгляда хватает процедуры sp_who2: в колонке BlkBy стоит номер блокирующего сеанса.

Чтобы ловить длительные блокировки автоматически, включают отчёт о заблокированных процессах: задают порог blocked process threshold через sp_configure и собирают событие Blocked process report расширенными событиями. В отчёте виден XML с обоими сеансами — тем, что ждёт, и тем, что держит ресурс, — вместе с текстами их запросов. Это снимает нужду сидеть у sp_who2 и ждать, пока блокировка повторится.

Для системного анализа блокировок в кластере используют Центр управления производительностью (ЦУП) из корпоративного инструментального пакета — он собирает события ТЖ и строит картину взаимных ожиданий без ручного разбора логов.

Что показывает SQL Server: профайлер и системные представления

Когда база работает в клиент-серверном варианте на MS SQL Server, тяжёлые запросы удобно разбирать средствами самой СУБД.

SQL Server Profiler перехватывает запросы в реальном времени: создаёте трассировку по событию RPC:Completed / SQL:BatchCompleted, фильтруете по Duration и видите текст, время и число чтений. Инструмент наглядный, но устаревший.

Расширенные события (Extended Events) — современная замена профайлера. Нагрузка на сервер заметно меньше, поэтому для боевой базы берут именно их: сессия xEvents по тем же событиям завершения запросов пишет данные в файл, который потом разбирают.

Системные представления (DMV) дают сводку без трассировки. Топ самых затратных запросов — по накопленной статистике:

SELECT TOP 20
    qs.total_worker_time / qs.execution_count AS среднее_cpu,
    qs.execution_count                        AS вызовов,
    SUBSTRING(t.text, qs.statement_start_offset / 2, 200) AS запрос
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS t
ORDER BY qs.total_worker_time DESC;

Ещё полезно посмотреть sys.dm_os_wait_stats — чего сервер ждёт чаще всего. Длинные ожидания типа PAGEIOLATCH указывают на дисковую подсистему, LCK_* — снова на блокировки.

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

Индексы и статистика: перестроение и обслуживание

Медленный запрос на стороне SQL часто упирается не в текст, а в индексы. Сервер либо сканирует таблицу целиком вместо поиска по индексу, либо строит план по устаревшей статистике.

Сначала оценивают фрагментацию:

SELECT OBJECT_NAME(ips.object_id) AS таблица,
       i.name                     AS индекс,
       ips.avg_fragmentation_in_percent AS фрагментация
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') AS ips
JOIN sys.indexes AS i
  ON i.object_id = ips.object_id AND i.index_id = ips.index_id
WHERE ips.avg_fragmentation_in_percent > 10
ORDER BY ips.avg_fragmentation_in_percent DESC;

Дальше действуют по уровню фрагментации:

ФрагментацияДействиеКоманда
10–30 %Реорганизация (лёгкая)ALTER INDEX ... REORGANIZE
больше 30 %ПерестроениеALTER INDEX ... REBUILD
—Обновить статистикуUPDATE STATISTICS
ALTER INDEX ALL ON _InfoRg12345 REBUILD;     -- фрагментация выше 30 %
ALTER INDEX ALL ON _InfoRg12345 REORGANIZE;  -- фрагментация 10–30 %

Перестроение индекса командой REBUILD без опции ONLINE блокирует таблицу на время операции. Опция ONLINE доступна только в редакции Enterprise. Запускайте перестроение в окно низкой активности, иначе пользователи упрутся в заблокированные таблицы.

Бывает, что индексы в порядке, а один и тот же запрос ведёт себя по-разному от запуска к запуску. Частая причина — план, построенный под нетипичное значение параметра и закэшированный для всех остальных. В такой ситуации помогает обновление статистики и повторная компиляция запроса; хронические случаи разбирают уже прицельно, с планом из профайлера.

Разовыми командами обслуживание не ограничивают — его ставят на регламент: план обслуживания SQL Server или готовый набор скриптов, который сам выбирает между реорганизацией и перестроением по проценту фрагментации и обновляет статистику.

В файловом варианте индексов SQL нет. Там обслуживание выполняют из конфигуратора: Администрирование → Тестирование и исправление информационной базы с включённой реиндексацией таблиц. Операция монопольная — все сеансы нужно закрыть.

Ошибки в тексте запроса, которые тормозят базу

Половину проблем создаёт не СУБД, а сам текст запроса на языке 1С. Самые частые:

  1. Запрос в цикле. Классика: по каждой строке табличной части выполняется отдельный запрос. Решение — вынести всё в один запрос и обработать результат выборкой или соединением с таблицей значений.
  2. Отбор у виртуальной таблицы через ГДЕ. У таблиц остатков и оборотов параметры отбора задают в скобках самой виртуальной таблицы, а не во внешнем ГДЕ. Иначе платформа сначала считает итоги по всему регистру, а уже потом отфильтрует — на больших регистрах это дорого.
  3. Обращение к реквизитам через точку у составного типа. Поле вида Ссылка.Владелец.Наименование, где Владелец составного типа, превращается в левые соединения со всеми таблицами этого типа. Уточняйте тип функцией ВЫРАЗИТЬ(... КАК ...).
  4. Соединения с подзапросами. Соединять лучше с временными таблицами, а не с подзапросами: по временной таблице можно построить индекс через ИНДЕКСИРОВАТЬ ПО.
  5. Фильтр, который не ложится на индекс. Условия с НЕ, с ПОДОБНО и шаблоном "%текст" в начале строки, а также отбор по неиндексированному полю заставляют сервер сканировать таблицу целиком.
  6. Лишние поля и ВЫБРАТЬ *. Чем меньше полей и строк тянет запрос, тем меньше работы у СУБД и тем выше шанс, что хватит покрывающего индекса.

Проверять эти места удобно связкой: текст запроса — из SDBL технологического журнала, реальный план — из planSQLText или из профайлера. Если план показывает Scan вместо Seek по большой таблице — почти наверняка виновато одно из условий выше.

Диагностика: выберите симптом

Частые вопросы

Можно ли посмотреть текст SQL-запроса, не настраивая технологический журнал?
Да, в клиент-серверном варианте текущие запросы видны через sys.dm_exec_requests с sys.dm_exec_sql_text, а историю самых затратных хранит sys.dm_exec_query_stats. Технологический журнал нужен, когда важен контекст конфигурации — из какого модуля пришёл запрос.
Чем «Замер производительности» отличается от технологического журнала?
Замер привязывает время к строкам кода конфигурации и запускается на конкретную операцию из конфигуратора. Технологический журнал пишет события платформы и СУБД непрерывно и ловит проблемы, которые воспроизводятся только под нагрузкой.
Как понять, что тормозят именно блокировки, а не медленный запрос?
По ожиданию без нагрузки: процессор и диск свободны, а операция висит. В технологическом журнале появляются события TTIMEOUT или TDEADLOCK, а на SQL Server у сеанса непустой blocking_session_id.
Нужно ли перестраивать индексы вручную?
Разово — да, когда запрос резко замедлился. Но правильнее поставить регламентное обслуживание, которое само реорганизует или перестраивает индексы по проценту фрагментации и обновляет статистику по расписанию.
Работает ли эта диагностика в файловой базе?
Частично. Консоль запросов, замер производительности и анализ текста запроса работают везде. Инструменты SQL Server (профайлер, системные представления, перестроение индексов) доступны только в клиент-серверном варианте.