Одной из частых проблем, с которой сталкиваются разработчики 1С при работе с регистрами сведений, является низкая скорость выполнения запроса к виртуальной таблице СрезПоследних. Когда такой запрос вызывается десятки раз в цикле, производительность системы падает, вызывая нарекания пользователей. В этой статье мы разберем основные причины такого поведения и рассмотрим пошаговые методы оптимизации.
Первое, на что стоит обратить внимание, — это алгоритмическая составляющая. Если вы выполняете запрос в цикле 65 раз подряд, как в нашем примере, проблема кроется не только в СУБД, но и в самой логике обмена данными между приложением и базой данных. Каждый вызов Запрос.Выполнить() — это сетевой запрос к серверу, получение плана выполнения, блокировки и чтение данных. Даже если каждый запрос длится доли секунды, их суммарное время в цикле становится критичным.
Основные факторы, влияющие на производительность:
Индексировать на всех измерениях часто приводят к обратному эффекту. СУБД может запутаться в выборе оптимального индекса и построить неэффективный план запроса.ЛюбаяСсылка), 1С вынуждена добавлять дополнительные поля в индекс для хранения типа ссылки. Это драматически замедляет поиск.СрезПоследних может ожидать снятия блокировок, что приводит к «замиранию» запроса.Давайте рассмотрим, как можно изменить наш подход, чтобы ускорить получение данных.
Вместо того чтобы «нырять» в базу каждый раз, выберите все необходимые данные одним запросом до начала цикла. Вы можете собрать все параметры Измерение1, Измерение2, Измерение3 в массив или таблицу значений, а затем сформировать запрос, который вернет результат сразу для всех нужных комбинаций.
Если данные требуются для отображения, используйте механизм кэширования в Соответствие или ТаблицаЗначений. Это перенесет нагрузку из СУБД в оперативную память сервера.
Разберемся с индексами. В 1С для регистров сведений, не подчиненных регистратору, индекс по комбинации Период и измерениям создается автоматически. Если вы добавили Индексировать к третьему измерению, вы создали дополнительный индекс. В большинстве случаев при отборе сразу по трем измерениям этот индекс бесполезен.
Попробуйте следующее:
Индексировать, если они не используются для отбора по этому конкретному полю в одиночку.Хотя виртуальная таблица СрезПоследних имеет параметры отбора, иногда перенос условий в секцию ГДЕ может помочь оптимизатору СУБД лучше понять план выполнения. Однако помните: для СрезПоследних критически важно, чтобы условия отбора соответствовали начальным полям индекса.
Пример оптимизированного кода с пакетным запросом:
// Вместо цикла используем пакетный запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Регистр.Измерение1,
| Регистр.Измерение2,
| Регистр.Измерение3,
| Регистр.Значение
|ИЗ
| РегистрСведений.УстановленныеПараметры.СрезПоследних(&Период, ) КАК Регистр
|ГДЕ
| Регистр.Измерение1 В (&СписокИзмерение1)
| И Регистр.Измерение2 В (&СписокИзмерение2)";
// Дальнейшая обработка данных в памяти сеанса
Результат = Запрос.Выполнить().Выгрузить();
// Полученные данные кэшируем в структуру или соответствие
Убедитесь, что в свойствах регистра сведений включено использование итогов. Если периодичность регистра установлена, например, в Запись, то для формирования среза последних система вынуждена перебирать записи, что очень медленно. При использовании итогов платформа поддерживает отдельную таблицу, где актуальные состояния уже рассчитаны, что позволяет получать данные практически мгновенно.
Для решения вашей задачи выполните следующие шаги:
Замер производительности в Конфигураторе, чтобы точно понять, сколько времени занимает именно запрос, а сколько — обработка полученных данных.Технологический журнал для выявления блокировок при чтении из регистра.Помните, что лучший запрос — это тот, который не выполняется. Кэширование данных на время сеанса часто дает гораздо больший прирост скорости, чем любая тонкая настройка индексов СУБД.