Как правильно использовать ПолучитьОбъект() для оптимизации производительности

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

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

Проблема избыточного вызова метода ПолучитьОбъект()

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

  1. Формирует и отправляет запрос к СУБД для получения всех реквизитов объекта, включая все его табличные части.
  2. Десериализует полученные данные в объектную модель 1С.
  3. Помещает объект в кэш объектов на сервере приложений.
  4. Инициализирует структуры, необходимые для работы механизмов записи и проведения.

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

Стратегия 1: Максимальная фильтрация на уровне запроса

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

Рассмотрим пример кода, где мы получаем данные табличной части сразу в запросе, чтобы не обращаться к объекту без нужды:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗаказКлиента.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.ЗаказКлиента КАК ЗаказКлиента
    |ГДЕ
    |	ЗаказКлиента.Проведен = ИСТИНА
    |	И ЗаказКлиента.Товары.Отменено = ЛОЖЬ
    |	И ЗаказКлиента.Товары.Номенклатура = &Номенклатура";

Запрос.УстановитьПараметр("Номенклатура", СсылкаНаТовар);
Выборка = Запрос.Выполнить().Выбрать();

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

Стратегия 2: Отложенное получение объекта (Lazy Loading)

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

Разберем по шагам предложенный на форуме вариант:

  1. Получаем данные табличной части запросом, связанным с основной выборкой.
  2. Обходим данные в цикле.
  3. Устанавливаем флаг Модифицированность.
  4. Вызываем ПолучитьОбъект() только при истинности флага.

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

Стратегия 3: Использование метода ВыбратьПоСсылкам()

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

Важные аспекты блокировок и транзакций

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

Сравнение типов: ТаблицаЗначений vs ТабличнаяЧасть

Важно понимать разницу, когда мы работаем с данными. Запрос возвращает результат в виде ВыборкаИзРезультатаЗапроса или ТаблицаЗначений. Это просто наборы данных в памяти. ТабличнаяЧасть документа (доступная через ПолучитьОбъект()) — это объектная структура, связанная с метаданными. Для анализа данных всегда выгоднее использовать РезультатЗапроса, так как он не тянет за собой весь контекст объекта и методы модуля объекта.

Рассмотрим пример правильного получения ТЧ через запрос без получения объекта:


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

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

Подводя итог, сформулируем основные правила работы с ПолучитьОбъект():

  1. Никогда не используйте ПолучитьОбъект(), если вам нужно просто прочитать реквизит или строку табличной части. Используйте запросы или обращение через точку (помня о неявных запросах).
  2. Старайтесь максимально сузить выборку в исходном запросе, чтобы метод вызывался только для тех записей, которые гарантированно требуют перезаписи.
  3. Если вы получили объект, но в процессе передумали его менять — не вызывайте Записать().
  4. Для ускорения процесса записи в тяжелых конфигурациях (ERP, УТ 11) используйте ДополнительныеСвойства объекта для передачи флагов в модуль объекта, чтобы отключить ненужные при программной обработке проверки.

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

← На главную