Как правильно рассчитать расход с отбором по типу документа: физическая или виртуальная таблица регистра?

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

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

Решение «в лоб»: запрос к физической таблице

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

Посмотрим на пример запроса:


ВЫБРАТЬ 
    ТоварыНаСкладах.Номенклатура КАК Номенклатура, 
    СУММА(ТоварыНаСкладах.ВНаличии) КАК Количество 
ИЗ 
    РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах 
ГДЕ 
    ТоварыНаСкладах.Номенклатура В (&СписокНоменклатуры) 
    И ТоварыНаСкладах.Склад = &Склад 
    И ТоварыНаСкладах.Период МЕЖДУ &НачалоПериода И &КонецПериода 
    И ТоварыНаСкладах.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход) 
    И ТипЗначения(ТоварыНаскладах.Регистратор) В (&СписокТипов) 
СГРУППИРОВАТЬ ПО 
    ТоварыНаСкладах.Номенклатура

Этот подход работает корректно и выполняет поставленную задачу. Мы явно указываем отбор по периоду, складу, списку номенклатуры, фильтруем по ВидДвиженияНакопления.Расход и ограничиваем типы регистраторов через функцию ТипЗначения. Однако у многих разработчиков возникает желание оптимизировать код и перевести его на использование виртуальной таблицы оборотов. Проанализируем, стоит ли это делать.

Попытка использования виртуальной таблицы оборотов

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

Рассмотрим пример кода, который часто получается в таких случаях:


ВЫБРАТЬ 
    ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, 
    ТоварыНаСкладахОбороты.ВНаличииРасход КАК Количество 
ИЗ 
    РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Склад = &Склад) КАК ТоварыНаСкладахОбороты 
ГДЕ 
    ТипЗначения(ТоварыНаСкладахОбороты.Регистратор) В (&СписокТипов)

Частая ошибка: При выполнении такого запроса можно столкнуться с ситуацией, когда система возвращает непонятную единицу вместо фактического количества расхода. Выясним причину. Если в виртуальной таблице указана периодичность Регистратор, но в секции выборки не выбрано поле регистратора, и при этом отсутствует агрегатная функция СУММА (или группировка настроена некорректно), то результат может схлопнуться неправильно. В итоге вы получаете первую попавшуюся запись или количество строк, а не сумму ресурсов.

Сравнение производительности: почему физическая таблица лучше?

Разберем подробнее архитектурные особенности платформы 1С:Предприятие, чтобы понять, какой из запросов будет работать быстрее.

  1. Индексы базы данных. Основной аргумент в пользу использования физической таблицы заключается в структуре индексов. Для регистров накопления платформа автоматически создает индекс по полям Период + Регистратор. При обращении к физической таблице с отбором по периоду и регистратору СУБД максимально эффективно использует этот индекс.
  2. Накладные расходы виртуальных таблиц. Виртуальная таблица оборотов предназначена для получения агрегированных (свернутых) данных. Когда мы запрашиваем её с периодичностью Регистратор, платформа всё равно вынуждена обращаться к основной физической таблице движений. При этом на сервер СУБД накладываются дополнительные вычислительные затраты на построение виртуальной таблицы «на лету». Это делает запрос медленнее.
  3. Стандарты разработки 1С. Согласно рекомендациям фирмы «1С», если для алгоритма или отчета требуются детальные записи с точностью до документа-регистратора (как в нашем случае, где идет жесткий отбор по типу документа), следует обращаться именно к физической таблице регистра. Виртуальные таблицы нужны там, где требуется общая свернутая сумма за период без детализации.

Оптимизация отбора по типу документа

Проанализируем условие ТипЗначения(Регистратор) В (&СписокТипов). Хотя оно рабочее, существуют и другие, иногда более оптимальные способы фильтрации:

  1. Использование оператора ССЫЛКА. Если типов документов немного, конструкцию можно переписать через логическое ИЛИ и оператор ССЫЛКА (например, Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг). На уровне SQL-сервера это генерирует более простой код без необходимости обращаться к таблицам метаданных для определения числового идентификатора типа.
  2. Передача массива пустых ссылок. Если типов много, использование ТипЗначения с передачей массива — это стандартный и хороший путь. Главное — передавать в параметр &СписокТипов массив именно типов значений (или пустых ссылок соответствующих типов документов). SQL-сервер обрабатывает такое условие по полю составного типа (_DocumentTRef) достаточно быстро.
  3. Использование временных таблиц. Для очень сложных и тяжелых отчетов можно сначала выбрать все документы нужных типов за период во временную таблицу, а затем соединить её с физической таблицей регистра по полю Регистратор. Это полностью исключит проверки типов в условии ГДЕ основного запроса к регистру.

Итоги

Подводя итог, можно с уверенностью сказать: для задачи расчета оборотов за период по конкретным типам документов первоначальное решение через физическую таблицу регистра с фильтром ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход) является самым грамотным и производительным.

Попытка переписать этот запрос на использование виртуальной таблицы с периодичностью по регистратору — это ложная оптимизация. Она не только усложняет чтение запроса, но и снижает скорость его выполнения, так как заставляет СУБД выполнять лишнюю работу по конструированию избыточной виртуальной выборки.

← На главную