Выборка данных в 1С: почему запрос эффективнее менеджера объекта и как избежать проблем с производительностью

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

В процессе разработки на платформе 1С:Предприятие перед программистом часто встает дилемма: использовать ли встроенные методы менеджеров объектов (например, Справочники.Номенклатура.Выбрать()) или написать полноценный запрос. На первый взгляд может показаться, что стандартная выборка проще в написании, однако при работе с реальными объемами данных она скрывает в себе серьезные риски для производительности системы. В этой статье мы подробно разберем, почему опытные разработчики отдают предпочтение запросам и чем опасен вызов метода ПолучитьОбъект() внутри цикла.

Анализ проблемы получения объекта в цикле

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


Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
    СправочникОбъект = Выборка.Ссылка.ПолучитьОбъект();
    // Какие-то действия с объектом
КонецЦикла;

Проанализируем, что происходит «под капотом» платформы при таком подходе. Метод ПолучитьОбъект() — это чрезвычайно ресурсоемкая операция. Когда мы вызываем его для каждой итерации цикла, платформа выполняет следующие действия:

  1. Множественные обращения к СУБД: Вместо одного компактного запроса к таблице платформа генерирует отдельный SQL-запрос для каждой ссылки. Если в справочнике 10 000 элементов, система выполнит как минимум 10 000 запросов к базе данных.
  2. Чтение избыточных данных: Объектная модель 1С подразумевает загрузку всех реквизитов объекта, включая его табличные части. Если вам нужно просто проверить значение одного флажка, платформа все равно прочитает из базы данных все многострочные части, описания и другие тяжелые данные.
  3. Инициализация модуля объекта: При получении объекта система компилирует его модуль и выполняет предопределенные события, такие как ПриЧтенииНаСервере. Это создает колоссальную нагрузку на процессор сервера приложений.

Важный вывод: использование ПолучитьОбъект() оправдано только в том случае, если вам действительно нужно изменить данные и записать их, либо если логика проверки настолько сложна, что она реализована исключительно в процедурах модуля объекта.

Сравнение методов: Запрос против Менеджера объекта

Разберем подробнее, чем отличается работа через Запрос от работы через метод Выбрать() менеджера справочника или документа.

1. Избирательность данных

В запросе мы можем четко указать только те поля, которые нам необходимы для работы. Например, если нам нужны только Ссылка и Артикул, мы пишем:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка КАК Ссылка,
    |   Номенклатура.Артикул КАК Артикул
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура";

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Такой подход минимизирует трафик между SQL-сервером и сервером 1С. В то время как метод Выбрать() менеджера объекта всегда подтягивает определенный набор стандартных полей и не дает такой гибкости.

2. Работа с ограничениями доступа (RLS)

Проанализируем критически важный нюанс, связанный с безопасностью. В запросах мы можем использовать ключевое слово РАЗРЕШЕННЫЕ. Это позволяет системе корректно обрабатывать ситуацию, когда у текущего пользователя нет прав на просмотр части записей. Если же использовать метод Выбрать() в условиях настроенного RLS (ограничения на уровне записей), программа может просто «упасть» с ошибкой нарушения прав доступа или вернуть некорректный результат, так как этот метод не всегда адекватно обрабатывает сложные правила ограничений в типовых конфигурациях.

3. Сортировка и фильтрация

Метод Выбрать() крайне ограничен в возможностях фильтрации. Вы можете установить отбор только по иерархии (владелец, родитель) или по индексированным полям. Запрос же позволяет соединять таблицы, использовать виртуальные таблицы остатков, накладывать любые условия в секции ГДЕ и сортировать данные по любому количеству полей.

Когда использовать Менеджер объекта?

Несмотря на явные преимущества запросов, метод Выбрать() может быть полезен в редких случаях:

Однако в промышленной разработке и при работе с высоконагруженными системами использование запросов является стандартом де-факто.

Как оптимизировать массовое изменение данных

Если ваша задача заключается в том, чтобы изменить реквизит у большого количества объектов, рассмотрим, как сделать это максимально эффективно. Вместо того чтобы получать объект прямо из выборки менеджера, лучше сначала получить список ссылок запросом, а затем обрабатывать их порциями.

Выясним причину, почему запись может идти медленно. Часто это связано с проверками в модуле объекта. Если бизнес-логика позволяет пропустить проверки (например, при техническом обновлении реквизитов), используйте свойство ОбменДанными.Загрузка.

Рассмотрим пример правильного цикла обработки:


Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ СтавкаНДС = &СтараяСтавка");
Запрос.УстановитьПараметр("СтараяСтавка", Перечисления.СтавкиНДС.НДС18);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Объект = Выборка.Ссылка.ПолучитьОбъект();
    Объект.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
    
    // Ускоряем запись, отключая лишние проверки
    Объект.ОбменДанными.Загрузка = Истина; 
    
    Попытка
        Объект.Записать();
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка записи объекта", УровеньЖурналаРегистрации.Ошибка,,, СообщитьОбОшибке(ОписаниеОшибки()));
    КонецПопытки;
КонецЦикла;

Миф о потреблении памяти

Существует заблуждение, что Запрос выгружает все данные в память сразу, а Выборка из менеджера работает порциями. На самом деле, оба метода при использовании объекта Выборка работают через курсоры. Данные подкачиваются с сервера порциями по мере вызова метода Следующий().

Важно: память переполняется только в том случае, если вы используете метод Запрос.Выполнить().Выгрузить(), который создает ТаблицуЗначений в оперативной памяти. Для больших массивов данных всегда используйте Выбрать().

Итоговые рекомендации

Подводя итог нашему анализу, сформулируем основные правила выбора инструмента для работы с данными в 1С:

  1. Всегда используйте Запрос, если вам нужно просто прочитать данные или отфильтровать их по сложным критериям. Это быстрее, надежнее с точки зрения прав доступа и экономнее по памяти.
  2. Избегайте ПолучитьОбъект() в тех случаях, когда данные нужны только для чтения. Пользуйтесь полями выборки запроса.
  3. Минимизируйте количество полей в тексте запроса. Выбирайте только то, что действительно будете использовать в коде.
  4. При массовом изменении объектов обязательно используйте ОбменДанными.Загрузка = Истина, если это не нарушает целостность данных и бизнес-логику вашей конфигурации.
  5. Помните про RLS: использование РАЗРЕШЕННЫЕ в запросах — залог стабильной работы программы под правами обычного пользователя.

Соблюдение этих простых принципов позволит вам создавать производительные и отказоустойчивые решения на платформе 1С, которые будут эффективно работать даже на огромных информационных базах.

← На главную