Снимаем и читаем план выполнения запроса в 1С
Содержание
План выполнения строит не 1С, а СУБД — MS SQL Server или PostgreSQL. 1С переводит запрос с внутреннего языка в SQL, отдаёт его серверу баз данных, и уже оптимизатор СУБД решает, как физически доставать данные. Поэтому задача «получить план запроса 1С» распадается на два шага: снять текст SQL, который реально ушёл на сервер, и получить для него план выполнения.
Снять план можно двумя путями. Первый — технологический журнал платформы: события DBMSSQL (MS SQL) и DBPOSTGRS (PostgreSQL) пишут текст SQL, а тег <plansql/> добавляет к ним сам план. Второй — средства СУБД: в PostgreSQL это команда EXPLAIN, в MS SQL — кнопка показа плана в SQL Server Management Studio. Разберём оба способа, научимся читать операторы и поймём, почему один и тот же запрос то летает, то висит минуту.
Где рождается план и что такое «запрос 1С» для сервера
В файловом варианте базу обслуживает встроенная СУБД, план от неё получить штатно нельзя. Всё, что ниже, относится к клиент-серверному варианту на MS SQL или PostgreSQL.
Запрос, который вы пишете на встроенном языке, проходит несколько превращений:
- 🔹 язык запросов 1С → внутреннее представление
SDBL; - 🔹
SDBL→ текст SQL под конкретную СУБД; - 🔹 SQL → план выполнения, который строит оптимизатор сервера.
Имена таблиц и полей в этом SQL — не Номенклатура и Контрагенты, а служебные _Reference123, _Document456 с полями вида _Fld789. Поэтому прочитать план «в лоб» мало — нужно сопоставить служебные имена с объектами конфигурации. Это делают по структуре хранения (в конфигураторе есть служебная таблица соответствия) либо автоматически — в специализированных инструментах анализа.
Если нужна только скорость кода, а не план, начните с замера производительности в конфигураторе (Отладка → Замер производительности). Он покажет, какая строка встроенного языка тратит время. Но SQL-план он не даёт — для него идём в технологический журнал или СУБД.
Способы снять план выполнения
Выбор инструмента зависит от того, есть ли у вас доступ к серверу СУБД и нужен ли план «боевого» запроса под реальной нагрузкой.
Технологический журнал платформы
Самый универсальный путь: план снимается там же, где работает проблемный запрос, под реальными данными. Настраивается файлом logcfg.xml в каталоге conf платформы.
Минимальная конфигурация для сбора планов тяжёлых запросов:
<config xmlns="http://v8.1c.ru/v8/tech-log">
<log location="C:\v8log" history="24">
<event>
<eq property="name" value="DBPOSTGRS"/>
<ge property="duration" value="1000000"/>
</event>
<property name="all"/>
<plansql/>
</log>
</config>
Разбор по строкам:
location— каталог для логов,history— сколько часов хранить.- Фильтр по событию:
DBPOSTGRSдля PostgreSQL,DBMSSQLдля MS SQL. durationв микросекундах:1000000— ловим только запросы дольше 1 секунды, чтобы не писать всё подряд.<plansql/>— главный тег: именно он добавляет к событию свойствоplanSQLTextс планом выполнения.
Технологический журнал без фильтра по duration на рабочей базе за минуты забьёт диск десятками гигабайт. Всегда ставьте порог длительности и короткий history, а после сбора данных журнал отключайте. Сам сбор планов добавляет нагрузку на сервер.
В логе каждое событие DBPOSTGRS/DBMSSQL покажет свойства Sql (текст запроса) и planSQLText (план). Платформа при этом подставляет в план реальные значения параметров — это ценно, потому что от параметра зависит выбор оптимизатора.
Средства СУБД напрямую
Когда SQL уже на руках (из журнала или из консоли запросов с показом SQL), план удобно снимать на самом сервере.
PostgreSQL — команда EXPLAIN:
-- только оценочный план, запрос не выполняется
EXPLAIN SELECT ...;
-- фактический план: запрос РЕАЛЬНО выполняется, с таймингом по операторам
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;
EXPLAIN (ANALYZE ...) действительно выполняет запрос. Для SELECT это безопасно, а вот INSERT/UPDATE/DELETE изменят данные. Оборачивайте такие проверки в транзакцию с откатом: BEGIN; EXPLAIN (ANALYZE) ...; ROLLBACK;.
MS SQL — SQL Server Management Studio:
Ctrl+L— показать оценочный план, без выполнения запроса;Ctrl+M— включить сбор фактического плана, план появится после выполнения;- либо профилировщик/расширенные события с планом
Showplan XML.
Специализированные инструменты
- ЦУП (Центр управления производительностью) из КИП — собирает планы автоматически и сразу привязывает их к контексту 1С: видно, какой документ и какая строка кода породили запрос. Удобно для разбора проблем на бою.
- Онлайн-визуализаторы планов PostgreSQL (например,
explain.tensor.ru) — вставляете текстовый выводEXPLAIN (ANALYZE)и получаете наглядное дерево с подсветкой узких мест. Данные при этом уходят на сторонний сервис — учитывайте для чувствительных баз.
duration и тегом <plansql/>. План снимется под реальной нагрузкой.EXPLAIN (ANALYZE, BUFFERS) в psql или pgAdmin, затем визуализатор для наглядности.Ctrl+M), смотрите толстые стрелки и операторы Scan.Логический и физический план: в чём разница
Это разные уровни одного процесса, и путать их — частая причина неверных выводов.
Логический план — что нужно сделать: какие таблицы соединить, по какому условию, что отфильтровать и сгруппировать. Он не зависит от того, как данные лежат на диске, и прямо следует из текста запроса.
Физический план — как именно сервер это выполнит: каким алгоритмом соединит таблицы, каким способом прочитает каждую. Его выбирает оптимизатор, опираясь на статистику, индексы и оценку стоимости вариантов.
Пример: логически «соединить заказы с контрагентами» — одно действие. Физически оптимизатор выберет между:
- Nested Loops — для каждой строки одной таблицы ищет совпадения во второй по индексу; хорош, когда строк мало;
- Hash Join / Hash Match — строит хеш-таблицу; хорош на больших объёмах;
- Merge Join — сливает два отсортированных потока.
Команды EXPLAIN и план в SSMS показывают именно физический план — то, что реально будет исполнено. Оценочный план (Ctrl+L, EXPLAIN без ANALYZE) — это предсказание оптимизатора. Фактический (Ctrl+M, EXPLAIN ANALYZE) — что произошло на самом деле. Главный диагностический сигнал — расхождение между оценочным и фактическим числом строк. Если оптимизатор ждал 10 строк, а пришло 2 000 000, он выбрал неподходящий алгоритм, и запрос будет медленным.
Как читать операторы графического плана
План читают от листьев к корню: сначала выполняются узлы чтения таблиц, затем соединения, сортировки, агрегации. В графическом плане толщина стрелок между узлами отражает поток строк — толстая стрелка там, где её быть не должно, и есть узкое место.
Ключевые операторы и что они значат:
| Оператор (MS SQL / PostgreSQL) | Что делает | Когда это сигнал проблемы |
|---|---|---|
| Index Seek / Index Scan | Точечный поиск по индексу | Норма, самый дешёвый доступ |
| Table Scan, Clustered Index Scan / Seq Scan | Полный проход таблицы | Плохо на большой таблице с выборкой немногих строк |
| Key Lookup, RID Lookup / Bitmap Heap Scan | Дочитывание строк по ссылке из индекса | Много таких — не хватает покрывающего индекса |
| Nested Loops / Nested Loop | Соединение циклом | Плохо, если внешних строк много |
| Hash Match / Hash Join | Соединение через хеш | Норма на объёмах; на мелких данных — перебор |
| Sort / Sort | Сортировка | Дорого; иногда её можно убрать индексом |
На что смотреть в первую очередь:
- Scan по большой таблице там, где ждали точечную выборку, — обычно значит, что индекс не подходит под условие.
- Расхождение
rowsоценочных и фактических (вEXPLAIN ANALYZE— полеrows=... actual rows=...) — проблема со статистикой или с оценкой параметра. - Самый дорогой узел по стоимости — отправная точка, но не приговор: стоимость в оценочном плане может врать именно из-за плохой статистики.
- Операторы Sort и Spill (сброс на диск) — признак нехватки памяти под операцию.
В PostgreSQL сразу смотрите последние строки вывода EXPLAIN ANALYZE: Planning Time и Execution Time. Если планирование дольше выполнения — запрос слишком сложный или много соединений.
Временные таблицы в плане запроса
Запросы 1С активно используют временные таблицы — через конструкцию ПОМЕСТИТЬ и менеджер временных таблиц. В SQL они превращаются во временные таблицы СУБД (#tt в MS SQL, временные таблицы в PostgreSQL). В плане они видны как отдельные шаги создания и чтения.
Главная тонкость: у временной таблицы по умолчанию нет ни индексов, ни полноценной статистики. Оптимизатор плохо оценивает, сколько в ней строк, и легко ошибается с алгоритмом соединения.
Что с этим делать на уровне запроса 1С:
- Индексируйте временные таблицы по полям соединения и отбора:
ПОМЕСТИТЬ ВТ ... ИНДЕКСИРОВАТЬ ПО Контрагент. - Не соединяйте в одном запросе много вложенных подзапросов — вынесите промежуточные наборы во временные таблицы. Оптимизатору проще работать с материализованным набором, чем с пятиэтажным подзапросом.
- Соединения с виртуальными таблицами регистров (остатки, обороты) тоже лучше предварительно складывать во временную таблицу, если результат используется дальше несколько раз.
Слишком много временных таблиц — тоже проблема: каждая порождает запись в служебную базу tempdb (MS SQL) и свои накладные расходы. Баланс важнее крайностей.
В плане обращайте внимание, читается ли временная таблица полным проходом (это нормально, если она маленькая) и не делает ли сервер по ней Nested Loops с большой таблицей — верный признак, что не хватило индекса на временной таблице.
Как индексы и статистика меняют план
Оптимизатор выбирает физический план не наугад, а по оценке стоимости. Основа оценки — статистика: гистограмма распределения значений в столбцах. По ней сервер прикидывает, сколько строк вернёт условие, и под это число подбирает операторы.
Отсюда два главных рычага:
Статистика. Если она устарела (данные выросли, а статистика помнит старое распределение), оценки будут неверными, и план — плохим. Обновление:
- PostgreSQL — команда
ANALYZE(и фоновыйautovacuum, который её запускает); - MS SQL —
UPDATE STATISTICSи авто-обновление статистики.
Признак устаревшей статистики в плане — именно то расхождение оценочных и фактических строк, о котором шла речь выше.
Индексы. Подходящий индекс превращает Scan в Seek. Но индекс помогает, только если условие отбора соответствует порядку полей в индексе. Индекс по (Организация, Дата) ускорит отбор по организации и по организации с датой, но не поможет отбору только по дате.
| Ситуация в плане | Вероятная причина | Что проверить |
|---|---|---|
| Seq Scan / Table Scan большой таблицы | Нет индекса под условие или он не выбран | Есть ли индекс по полям отбора |
| Оценка строк далека от факта | Устаревшая статистика | Запустить ANALYZE / UPDATE STATISTICS |
| Много Key Lookup | Индекс не покрывает нужные поля | Покрывающий индекс |
| Разный план на разных параметрах | Перекос данных, sniffing параметра | Статистика, принудительная перекомпиляция |
Индексы в 1С задают на уровне конфигурации (реквизиты, измерения регистров, индексирование реквизитов), и платформа создаёт их в СУБД. Прямое создание индексов в СУБД в обход конфигурации 1С не поддерживает — такой индекс платформа может удалить при реструктуризации.
Регламентная операция Тестирование и исправление в 1С чистит и переиндексирует данные на уровне платформы, но обслуживание индексов и статистики СУБД (перестроение, дефрагментация) — отдельная задача администратора на стороне сервера.
Ошибки при чтении плана запроса
Разобрать план правильно не менее важно, чем его снять. Пять ловушек, на которых чаще всего спотыкаются:
- Смотрят только оценочный план. Он показывает намерения оптимизатора, а не реальность. Проблему с объёмом данных видно лишь в фактическом плане (
EXPLAIN ANALYZE,Ctrl+M). - Гонятся за узлом с наибольшим процентом стоимости. Стоимость — оценка. При плохой статистике самый «дорогой» по проценту узел может быть ни при чём, а настоящий тормоз — там, где оценка занижена.
- Считают любой Scan злом. Полный проход маленькой таблицы (справочник на 50 строк) дешевле, чем поход через индекс. Scan плох только на большой таблице при выборке немногих строк.
- Снимают план на пустой или тестовой базе. На 100 записях оптимизатор выберет один план, на 10 миллионах — другой. План нужен на объёме, близком к боевому.
- Забывают про параметры. Один и тот же запрос с разными значениями параметра может получить разные планы из-за перекоса данных. Снимайте план с теми значениями, на которых реально тормозит.
Не делайте выводов по одному запуску EXPLAIN ANALYZE: первый прогон мог читать данные с диска, второй — уже из кеша. Сравнивайте повторные запуски.
Частые вопросы
Можно ли получить план запроса средствами самой 1С, без доступа к СУБД?
<plansql/>, доступ к серверу СУБД для этого не нужен, достаточно прав на платформе и к каталогу логов. Замер производительности и консоль запросов показывают время и SQL, но не план выполнения.Чем отличается оценочный план от фактического?
Почему в плане служебные имена вроде `_Reference123` вместо таблиц конфигурации?
Безопасно ли снимать план на рабочей базе?
EXPLAIN без ANALYZE и оценочный план в SSMS — да, запрос не выполняется. EXPLAIN (ANALYZE) выполняет запрос — для изменяющих данные операций оборачивайте в транзакцию с откатом. Технологический журнал всегда ограничивайте фильтром по duration, иначе переполните диск.