Почему отчет в 1С может работать быстро, а иногда зависать на несколько часов?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

В этой статье мы подробно разберем, почему возникает такое поведение, особенно в конфигурациях вроде "Управление торговлей 11" (УТ 11), "ERP" или "Комплексная автоматизация", где активно используется механизм ограничения прав доступа на уровне записей (RLS). Мы проанализируем технические аспекты работы платформы 1С в связке с MS SQL Server и выработаем стратегию решения.

1. Влияние RLS (Row Level Security) на производительность

В обсуждаемой теме автор указал, что в базе включен RLS (ограничение доступа на уровне записей), и каждый пользователь видит только свои данные. Это один из ключевых факторов.

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

Что происходит внутри:

  1. Ваш отчет — это "простыня" кода на 5 экранов.
  2. RLS добавляет к каждой таблице в этом запросе еще несколько скрытых соединений (JOIN) или условий (WHERE).
  3. В итоге SQL Server получает монструозный запрос, который в разы сложнее того, что вы написали в конфигураторе.

Если в коде запроса вы забыли ключевое слово РАЗРЕШЕННЫЕ, система будет пытаться проверить права даже на те записи, которые, возможно, будут отсечены дальнейшими условиями, что создает колоссальную нагрузку.

Рекомендация: Всегда используйте РАЗРЕШЕННЫЕ в запросах отчетов, если логика не требует обратного.


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Продажи.Номенклатура,
    Продажи.КоличествоОборот
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты AS Продажи

2. Проблема Parameter Sniffing (Сниффинг параметров) в MS SQL

Это наиболее вероятная причина того, почему отчет "то работает, то тормозит". Рассмотрим механизм работы оптимизатора запросов MS SQL Server.

Когда запрос выполняется впервые (или после очистки кэша), SQL Server строит план выполнения. Он смотрит на параметры, с которыми запущен отчет в данный момент.

Сценарий возникновения проблемы:

  1. Пользователь "А" (у которого доступ только к одному складу и мало данных) запускает отчет за один день.
  2. SQL Server видит: "Ага, выборка маленькая". Он строит план выполнения, оптимизированный под малое количество строк (например, используя алгоритм Nested Loops). Этот план сохраняется в кэше.
  3. Пользователь "Б" (директор, у которого доступ ко всем данным) запускает этот же отчет за год.
  4. SQL Server проверяет кэш, находит уже готовый план (построенный для пользователя "А") и пытается применить его к миллионам записей.
  5. Алгоритм, который был быстр для 100 строк, становится фатальным для 1 000 000 строк. Отчет зависает на часы.

В тестовой базе это не воспроизводится, потому что там кэш планов обычно пустой или другой, и для вашего теста SQL строит свежий, адекватный план.

3. Неоптимальная работа с виртуальными таблицами

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

Плохой подход:


ВЫБРАТЬ
    ...
ИЗ
    Справочник.Номенклатура КАК Спр
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
    ПО Спр.Ссылка = Остатки.Номенклатура
ГДЕ
    Спр.Ссылка В (&СписокТоваров)

В этом случае сначала может быть рассчитана полная виртуальная таблица остатков (по всем товарам), и только потом произойдет соединение. Если добавить сюда RLS, SQL Server может окончательно запутаться в выборе плана.

Правильный подход:

Мы должны помочь оптимизатору. Для этого необходимо сначала отобрать нужные данные во временную таблицу, а затем использовать параметры виртуальной таблицы.


// Шаг 1: Помещаем список товаров во временную таблицу
ВЫБРАТЬ
    Т.Ссылка
ПОМЕСТИТЬ ВТ_Товары
ИЗ
    Справочник.Номенклатура КАК Т
ГДЕ
    Т.Ссылка В (&СписокТоваров);

// Шаг 2: Используем отбор внутри параметров виртуальной таблицы
ВЫБРАТЬ
    ...
ИЗ
    ВТ_Товары КАК Товары
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки( , 
        Номенклатура В (ВЫБРАТЬ Ссылка ИЗ ВТ_Товары)
    ) КАК Остатки
    ПО Товары.Ссылка = Остатки.Номенклатура

Это критически важно при использовании RLS. Чем проще и "атомарнее" запросы, тем меньше шансов, что SQL Server выберет неверный план.

4. Устаревание статистики и блокировки

Еще одна причина, по которой отчеты могут вести себя непредсказуемо, — это устаревшая статистика (Statistics) на SQL Server или проблемы с базой tempdb.

Статистика: Если отчет активно использует временные таблицы, и в них записывается большое количество данных, SQL Server может не успеть обновить статистику. Он будет "думать", что во временной таблице 1 строка, хотя там их 100 000. В результате — неверный выбор типа соединения (Join) и медленная работа.

Фоновая нагрузка: Проверьте, не запускаются ли в момент "тормозов" регламентные задания (например, обновление полнотекстового индекса, обмен данными или резервное копирование). Даже если отчет только читает данные, высокая нагрузка на диск или процессор сервера (особенно при схеме питания "Сбалансированная" вместо "Высокая производительность") может замедлить выполнение сложных выборок.

5. Стратегия решения проблемы

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

  1. Анализ Технологического журнала (ТЖ).

    Настройте технологический журнал для сбора событий TTIMEOUT, TLOCK и долгих запросов. Это покажет, на чем именно висит система: на ожидании ресурсов или на выполнении самого запроса.

  2. Рефакторинг текста запроса.

    Разбейте большую "простыню" запроса на последовательные пакеты с использованием менеджера временных таблиц. Избегайте соединений "всего со всем" в одном запросе. Уберите обращения "через точку" к полям составного типа (например, Документ.Партнер.ОсновнойМенеджер), так как при RLS это вызывает неявные тяжелые соединения.

  3. Борьба с Parameter Sniffing.

    Если проблема подтвердится (сброс кэша процедур DBCC FREEPROCCACHE на SQL сервере временно "лечит" отчет), можно попробовать использовать в запросах конструкцию, заставляющую SQL перекомпилировать план, но в языке запросов 1С это не всегда доступно напрямую.

    Более надежный способ в рамках 1С: если отчет сложный и с RLS, вынесите выборку данных в Привилегированный модуль. В этом случае:

    • В привилегированном модуле RLS отключается.
    • Вы выбираете "сырые" данные с фильтрацией по параметрам (Даты, Организация и т.д.).
    • Результат (например, таблицу значений или временную таблицу) возвращаете в отчет.
    • В самом отчете (СКД) накладываете финальные фильтры.

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

Заключение

Проблема "то быстро, то медленно" почти всегда кроется на стыке работы оптимизатора СУБД и механизма RLS платформы 1С. Ваша задача — максимально упростить жизнь оптимизатору: использовать РАЗРЕШЕННЫЕ, разбивать сложные запросы на простые этапы через временные таблицы и следить за актуальностью статистики на сервере СУБД.

← На главную