Почему зависает запрос с РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ ПЕРВЫЕ в 1С и как это исправить

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

При разработке и доработке конфигураций 1С разработчики иногда сталкиваются с ситуацией, когда простой запрос к справочнику начинает выполнять операцию недопустимо долго или полностью зависает. Проанализируем типичный пример такого запроса, разберем причины возникновения проблемы на уровне платформы 1С и СУБД, а также рассмотрим варианты решения.

Проблема: зависание запроса при получении уникальных значений

Рассмотрим запрос в 1С, сгенерированный типовыми алгоритмами или написанный вручную:


ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ ПЕРВЫЕ 51
    ТаблицаСправочника.AB_Партнер
ИЗ
    Справочник.Номенклатура КАК ТаблицаСправочника
ГДЕ
    ТаблицаСправочника.ВидНоменклатуры = &ВидНоменклатуры

На первый взгляд, выборка 51 уникальной записи из таблицы размером всего в несколько тысяч элементов должна выполняться за доли секунды. Однако в реальности такой запрос может зависать на десятки секунд или минут. При этом добавление в поля выборки Ссылка или замена на группировку мгновенно устраняет проблему.

Причины зависания и особенности работы СУБД

Выясним, почему возникает данная проблема. На время выполнения запроса влияют сразу несколько факторов:

  1. Отсутствие индекса по полю отбора. Операция фильтрации выполняется в секции ГДЕ по полю ВидНоменклатуры. Если для этого поля в метаданных не включена индексация, СУБД вынуждена выполнять полное сканирование таблицы (Table Scan / Index Scan). Обычного индексирования только выводимого реквизита AB_Партнер в этом случае недостаточно.
  2. Сочетание конструкций РАЗЛИЧНЫЕ и ПЕРВЫЕ без сортировки. Когда оптимизатор СУБД пытается найти первые 51 уникальных значений (операторы DISTINCT и TOP в SQL) без явной конструкции УПОРЯДОЧИТЬ ПО, он строит план, рассчитывая на быструю остановку сканирования. Если подходящие записи в базе распределены неравномерно или редко, СУБД начинает последовательно просматривать весь объем данных таблицы, вызывая колоссальную нагрузку.
  3. Влияние RLS (ключевое слово РАЗРЕШЕННЫЕ). Если в базе действуют ограничения прав на уровне записей, платформа 1С автоматически подставляет условия проверки прав. В сочетании с оператором РАЗЛИЧНЫЕ это существенно усложняет план выполнения, заставляя СУБД выполнять емкие операции агрегации в памяти или временной базе TempDB.
  4. Сниффинг параметров (Parameter Sniffing). Если при первом вызове план выполнения был зафиксирован для вида номенклатуры с большим количеством совпадений, а затем запрос вызывается для редкого значения, скомпилированный план СУБД становится крайне неэффективным.

Варианты решения проблемы

Разберем по шагам доступные способы устранения зависания запроса.

1. Индексирование реквизита отбора в 1С

Первый шаг со стороны конфигуратора — убедиться, что поле, по которому происходит фильтрация в условии ГДЕ, проиндексировано. Если поиск идет по полю ВидНоменклатуры, настроем его свойства:

  1. Откроем дерево метаданных и найдем справочник Номенклатура.
  2. Перейдем в свойства реквизита ВидНоменклатуры.
  3. Установим значение свойства Индексировать в Индексировать или Индексировать с доп. упорядочиванием.
  4. Выполним обновление конфигурации базы данных.

2. Оптимизация текста запроса

Если есть возможность корректировать код запроса, примените один из следующих подходов:

Вариант А. Замена РАЗЛИЧНЫЕ на ГРУППИРОВАТЬ ПО:


ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 51
    ТаблицаСправочника.AB_Партнер КАК AB_Партнер
ИЗ
    Справочник.Номенклатура КАК ТаблицаСправочника
ГДЕ
    ТаблицаСправочника.ВидНоменклатуры = &ВидНоменклатуры
ГРУППИРОВАТЬ ПО
    ТаблицаСправочника.AB_Партнер

Вариант Б. Явное упорядочивание по проиндексированному полю:


ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ ПЕРВЫЕ 51
    ТаблицаСправочника.AB_Партнер КАК AB_Партнер
ИЗ
    Справочник.Номенклатура КАК ТаблицаСправочника
ГДЕ
    ТаблицаСправочника.ВидНоменклатуры = &ВидНоменклатуры
УПОРЯДОЧИТЬ ПО
    ТаблицаСправочника.Ссылка

Явное упорядочивание заставляет оптимизатор СУБД использовать заведомо проиндексированное поле Ссылка, благодаря чему выборка первых 51 записей происходит прогнозируемо и быстро.

3. Обслуживание СУБД

Если изменять запрос или метаданные нельзя, проверьте состояние сервера баз данных:

  1. Обновление статистики: Выполните полнотекстовое обновление статистики для таблиц справочника (команда UPDATE STATISTICS с параметром FULLSCAN в MS SQL Server). Это позволит оптимизатору корректно оценивать распределение данных.
  2. Очистка кэша планов: Сбросьте зависший план выполнения с помощью команды DBCC FREEPROCCACHE или перезапуска службы СУБД, чтобы устранить последствия Parameter Sniffing.
← На главную