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