Как ускорить медленно работающий запрос к виртуальной таблице СрезПоследних регистра сведений

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

Проблема производительности при получении последних значений из регистров сведений — одна из самых распространенных в практике разработчика 1С. Ситуация, когда простой запрос к виртуальной таблице СрезПоследних начинает выполняться десятки секунд, может парализовать работу системы, особенно если этот регистр является высоконагруженным (100+ пользователей). Разберем по шагам, почему это происходит и как оптимизировать работу с такими данными.

Анализ неэффективного использования запросов в циклах

Первое, на что стоит обратить внимание в предоставленном примере — это количество вызовов. Автор указывает, что 65 вызовов запроса выполняются за 46 секунд. Проанализируем ситуацию: выполнение запроса в цикле — это всегда «антипаттерн». Каждый вызов порождает отдельное обращение к СУБД, контекстные переключения и накладные расходы платформы.

Рассмотрим, как можно оптимизировать этот процесс. Вместо того чтобы вызывать запрос 65 раз для каждого набора измерений, нам следует собрать все необходимые параметры во временную таблицу и выполнить одно соединение. Это позволит СУБД построить единый план выполнения и обработать данные пакетом.

Рекомендация: Всегда заменяйте запросы в цикле на один пакетный запрос с использованием временных таблиц или передачей массива в параметры условия В (&МассивПараметров).

Оптимизация структуры индексов и порядка измерений

Выясним причину, по которой СУБД может игнорировать индексы. В регистрах сведений 1С автоматически создает индекс по комбинации Период + Измерения. Однако порядок этих измерений в конфигураторе критически важен. Если вы делаете отбор по Измерение2 и Измерение3, но пропускаете Измерение1, которое стоит первым в списке, СУБД может не использовать индекс эффективно (произойдет сканирование индекса вместо поиска).

Проанализируем правила работы составного индекса:

  1. Индекс работает наиболее эффективно, когда отбор идет по первым полям в его составе.
  2. Если в запросе часто отсутствует отбор по первому измерению, это измерение стоит переместить ниже в списке метаданных.
  3. Флаг Индексировать на конкретном измерении создает дополнительный индекс, который может помочь, если это измерение используется в отборах без учета других, но это также увеличивает размер базы и замедляет запись.

В нашем случае, если Измерение1 в 90% случаев не используется, его следует сделать последним в списке измерений регистра. Это позволит поиску по Измерение2 и Измерение3 попадать в начало основного индекса.

Замена виртуальной таблицы СрезПоследних на физическую таблицу

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

Разберем альтернативный подход, предложенный опытными разработчиками: использование прямой выборки из основной таблицы регистра. Посмотрим на пример кода, который часто работает быстрее на больших объемах данных:


Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1
                      |    Т.Значение КАК Значение
                      |ИЗ
                      |    РегистрСведений.УстановленныеПараметры КАК Т
                      |ГДЕ
                      |    Т.Период <= &Период
                      |    И Т.Измерение1 = &Измерение1
                      |    И Т.Измерение2 = &Измерение2
                      |    И Т.Измерение3 = &Измерение3
                      |УПОРЯДОЧИТЬ ПО
                      |    Т.Период УБЫВ");

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

Использование механизма итогов среза последних

Начиная с версии платформы 8.3.13, для периодических регистров сведений можно включить использование итогов. Разберем, как это помогает:

Проанализируем контекст использования: если вашим пользователям чаще всего нужно значение «на сейчас», обязательно включите флаг Разрешить итоги среза последних в свойствах регистра и убедитесь, что в коде в параметр периода передается Неопределено или пустая дата.

Влияние типов данных (Планы видов характеристик)

Если одно из измерений имеет составной тип или тип ПланВидовХарактеристикСсылка, это может усложнять запрос. Посмотрим на ситуацию глубже: если значение измерения является ссылкой на ПВХ, а в запросе используются поля через точку или сложные условия, это приводит к многочисленным JOIN в SQL-запросе.

Если производительность критична, рассмотрим вариант использования «Ключей аналитики». Вместо трех измерений в регистре (например, Организация, Склад, Номенклатура) создается одно измерение со ссылкой на вспомогательный справочник, содержащий эти три реквизита. Это делает индекс максимально компактным, а поиск — мгновенным.

Техническое обслуживание базы данных

Не стоит забывать и о системных факторах. В обсуждении упоминается, что проблема «плавающая». Это верный признак проблем со статистикой СУБД или фрагментацией индексов.

Проанализируем рекомендации для системного администратора:

  1. Обновление статистики: Если данные в регистре часто меняются, статистика SQL Server устаревает, и оптимизатор выбирает неверный план (например, Index Scan вместо Index Seek).
  2. Очистка процедурного кеша: Иногда помогает команда DBCC FREEPROCCACHE, если в кеше «застрял» неэффективный план выполнения.
  3. Реиндексация: При размере индекса в 2.9 Гб (что в два раза больше объема самих данных, как в примере автора), фрагментация может достигать критических значений, замедляя чтение с диска.

Таким образом, для решения проблемы медленного выполнения запроса необходимо комбинировать программные методы (отказ от циклов, использование ПЕРВЫЕ 1) и административные меры (настройка индексов и обслуживание СУБД).

← На главную