Проблема производительности при получении последних значений из регистров сведений — одна из самых распространенных в практике разработчика 1С. Ситуация, когда простой запрос к виртуальной таблице СрезПоследних начинает выполняться десятки секунд, может парализовать работу системы, особенно если этот регистр является высоконагруженным (100+ пользователей). Разберем по шагам, почему это происходит и как оптимизировать работу с такими данными.
Первое, на что стоит обратить внимание в предоставленном примере — это количество вызовов. Автор указывает, что 65 вызовов запроса выполняются за 46 секунд. Проанализируем ситуацию: выполнение запроса в цикле — это всегда «антипаттерн». Каждый вызов порождает отдельное обращение к СУБД, контекстные переключения и накладные расходы платформы.
Рассмотрим, как можно оптимизировать этот процесс. Вместо того чтобы вызывать запрос 65 раз для каждого набора измерений, нам следует собрать все необходимые параметры во временную таблицу и выполнить одно соединение. Это позволит СУБД построить единый план выполнения и обработать данные пакетом.
Рекомендация: Всегда заменяйте запросы в цикле на один пакетный запрос с использованием временных таблиц или передачей массива в параметры условия В (&МассивПараметров).
Выясним причину, по которой СУБД может игнорировать индексы. В регистрах сведений 1С автоматически создает индекс по комбинации Период + Измерения. Однако порядок этих измерений в конфигураторе критически важен. Если вы делаете отбор по Измерение2 и Измерение3, но пропускаете Измерение1, которое стоит первым в списке, СУБД может не использовать индекс эффективно (произойдет сканирование индекса вместо поиска).
Проанализируем правила работы составного индекса:
В нашем случае, если Измерение1 в 90% случаев не используется, его следует сделать последним в списке измерений регистра. Это позволит поиску по Измерение2 и Измерение3 попадать в начало основного индекса.
Иногда виртуальная таблица СрезПоследних работает медленно из-за сложности генерируемого SQL-кода, особенно если указан конкретный параметр &Период. В этом случае СУБД выполняет вложенный запрос с поиском максимального периода для каждой комбинации измерений.
Разберем альтернативный подход, предложенный опытными разработчиками: использование прямой выборки из основной таблицы регистра. Посмотрим на пример кода, который часто работает быстрее на больших объемах данных:
Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1
| Т.Значение КАК Значение
|ИЗ
| РегистрСведений.УстановленныеПараметры КАК Т
|ГДЕ
| Т.Период <= &Период
| И Т.Измерение1 = &Измерение1
| И Т.Измерение2 = &Измерение2
| И Т.Измерение3 = &Измерение3
|УПОРЯДОЧИТЬ ПО
| Т.Период УБЫВ");
Этот метод особенно эффективен, когда вам нужно получить значение по конкретному набору измерений. СУБД просто находит подходящую запись в индексе и берет самую верхнюю (последнюю по времени), не вычисляя итоги по всей таблице.
Начиная с версии платформы 8.3.13, для периодических регистров сведений можно включить использование итогов. Разберем, как это помогает:
СрезПоследних без указания параметра &Период (на текущий момент) будет перенаправлен к этой таблице, что дает колоссальный прирост скорости.СрезПоследних конкретную дату в прошлом, система всё равно будет обращаться к основной таблице, и итоги не помогут.Проанализируем контекст использования: если вашим пользователям чаще всего нужно значение «на сейчас», обязательно включите флаг Разрешить итоги среза последних в свойствах регистра и убедитесь, что в коде в параметр периода передается Неопределено или пустая дата.
Если одно из измерений имеет составной тип или тип ПланВидовХарактеристикСсылка, это может усложнять запрос. Посмотрим на ситуацию глубже: если значение измерения является ссылкой на ПВХ, а в запросе используются поля через точку или сложные условия, это приводит к многочисленным JOIN в SQL-запросе.
Если производительность критична, рассмотрим вариант использования «Ключей аналитики». Вместо трех измерений в регистре (например, Организация, Склад, Номенклатура) создается одно измерение со ссылкой на вспомогательный справочник, содержащий эти три реквизита. Это делает индекс максимально компактным, а поиск — мгновенным.
Не стоит забывать и о системных факторах. В обсуждении упоминается, что проблема «плавающая». Это верный признак проблем со статистикой СУБД или фрагментацией индексов.
Проанализируем рекомендации для системного администратора:
Index Scan вместо Index Seek).DBCC FREEPROCCACHE, если в кеше «застрял» неэффективный план выполнения.Таким образом, для решения проблемы медленного выполнения запроса необходимо комбинировать программные методы (отказ от циклов, использование ПЕРВЫЕ 1) и административные меры (настройка индексов и обслуживание СУБД).