Оптимизация запроса к регистру сведений
Условие
Оптимизируйте следующий запрос по производительности:
ВЫБРАТЬ
Цены.Номенклатура.Наименование КАК НаименованиеТовара,
Цены.Номенклатура.Артикул КАК Артикул,
Цены.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних() КАК Цены
ГДЕ
Цены.Номенклатура.Родитель = &ГруппаНоменклатуры
Подсказка
Обратите внимание на:
- Обращение к реквизитам через точку
- Условие в секции ГДЕ для виртуальной таблицы
- Использование конструкций ВЫРАЗИТЬ и ССЫЛКА для оптимизации
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Оптимизация запроса к регистру сведений
Это классическая задача оптимизации 1С-запросов. Исходный запрос имеет несколько проблем, которые негативно влияют на производительность. Рассмотрим их и предложим решение.
Проблемы исходного запроса
1. Обращение через точку к реквизитам справочника
Цены.Номенклатура.Наименование КАК НаименованиеТовара,
Цены.Номенклатура.Артикул КАК Артикул,
Это заставляет СУБД искать полный путь, что создаёт дополнительную нагрузку.
2. СрезПоследних() выполняется на БД
Виртуальная таблица СрезПоследних() — это дорогая операция, если её параметры не оптимальны.
3. Условие на реквизит справочника в ГДЕ
Сопоставление через .Родитель требует дополнительных операций СУБД.
Оптимизированное решение
Процедура ПолучитьЦеныОптимизировано(ГруппаНоменклатуры)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК НаименованиеТовара,
| Номенклатура.Артикул КАК Артикул,
| ЦеныПоследние.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура ССЫЛКА Справочник.Номенклатура) КАК ЦеныПоследние
|ЛЕВОЕ СОЕДИНЕНИЕ
| Справочник.Номенклатура КАК Номенклатура
|ПО
| ЦеныПоследние.Номенклатура = Номенклатура.Ссылка
|ГДЕ
| Номенклатура.Родитель = &ГруппаНоменклатуры
| И НЕ Номенклатура.ПометкаУдаления
|УПОРЯДОЧИТЬ ПО
| Номенклатура.Наименование";
Запрос.УстановитьПараметр("ГруппаНоменклатуры", ГруппаНоменклатуры);
Результат = Запрос.Выполнить().Выбрать();
КонецПроцедуры
Альтернативное решение (ещё более оптимальное)
Процедура ПолучитьЦеныЧерезЗапросКоллекции(ГруппаНоменклатуры)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| НоменклатураПовиток.Ссылка КАК НоменклатураСсылка
|ИЗ
| Справочник.Номенклатура КАК НоменклатураПовиток
|ЛЕВОЕ СОЕДИНЕНИЕ
| Справочник.Номенклатура КАК НоменклатураРодитель
|ПО
| НоменклатураПовиток.Родитель = НоменклатураРодитель.Ссылка
|ГДЕ
| НоменклатураПовиток.Родитель = &ГруппаНоменклатуры
| И НЕ НоменклатураПовиток.ПометкаУдаления";
Запрос.УстановитьПараметр("ГруппаНоменклатуры", ГруппаНоменклатуры);
РеквизитыНоменклатуры = Новый ТаблицаЗначений;
РеквизитыНоменклатуры.Колонки.Добавить("Ссылка");
РеквизитыНоменклатуры.Колонки.Добавить("Наименование");
РеквизитыНоменклатуры.Колонки.Добавить("Артикул");
РеквизитыНоменклатуры.Колонки.Добавить("Цена");
НоменклатураСсылки = Запрос.Выполнить().ВыгрузитьКолонку("НоменклатураСсылка");
// Получаем последние цены только для отобранных товаров
ЗапросЦены = Новый Запрос;
ЗапросЦены.Текст =
"ВЫБРАТЬ
| Цены.Номенклатура,
| Цены.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура В(&МассивНоменклатуры)) КАК Цены";
ЗапросЦены.УстановитьПараметр("МассивНоменклатуры", НоменклатураСсылки);
ТаблицаЦен = ЗапросЦены.Выполнить().ВыгрузитьВТаблицу();
КонецПроцедуры
Решение 3: Кэширование в памяти (для часто вызываемых данных)
ПеременнаяКэш.ЦеныНоменклатуры = Неопределено;
ПеременнаяКэш.ВремяОбновления = '00010101';
Процедура ПолучитьЦеныСКэшем(ГруппаНоменклатуры)
// Проверяем кэш (кэшируем 5 минут)
ТекущееВремя = ТекущаяДата();
Если ПеременнаяКэш.ЦеныНоменклатуры <> Неопределено
И ТекущееВремя - ПеременнаяКэш.ВремяОбновления < 300 Тогда
Возврат ПеременнаяКэш.ЦеныНоменклатуры;
КонецЕсли;
// Выполняем оптимизированный запрос
Результат = ПолучитьЦеныОптимизировано(ГруппаНоменклатуры);
// Обновляем кэш
ПеременнаяКэш.ЦеныНоменклатуры = Результат;
ПеременнаяКэш.ВремяОбновления = ТекущееВремя;
Возврат Результат;
КонецПроцедуры
Ключевые оптимизации
- Явное СОЕДИНЕНИЕ — вместо обращения через точку
- Фильтр ССЫЛКА в СрезПоследних() — указываем тип данных явно
- ЛЕВОЕ СОЕДИНЕНИЕ — получаем реквизиты из справочника
- Добавлена сортировка — для удобства и предсказуемости
- Кэширование — для часто используемых данных
Сравнение производительности
| Подход | Скорость | Затраты памяти | Сложность |
|---|---|---|---|
| Исходный запрос | Медленно | Средние | Простой |
| Оптимизация 1 | Быстро | Средние | Средняя |
| Оптимизация 2 | Очень быстро | Средние | Высокая |
| С кэшем | Очень быстро | Высокие | Высокая |
Рекомендация
Используйте Решение 1 (ЛЕВОЕ СОЕДИНЕНИЕ) — это оптимальный баланс между производительностью и простотой кода. Если запрос вызывается часто и данные стабильны, добавьте кэширование.