В процессе разработки на платформе 1С:Предприятие часто возникает задача получения данных из табличных частей документов (например, "Инвентаризация товаров") с необходимостью фильтрации или группировки по реквизитам, находящимся в шапке этого документа (например, по Складу или Дате). На первый взгляд задача кажется тривиальной, однако при работе с большими объемами данных неправильный подход к написанию запроса может привести к существенному замедлению работы системы. Рассмотрим подробнее, как эффективно решать эту задачу, разберем типичные ошибки и проанализируем различные способы оптимизации.
Самый простой и интуитивно понятный способ — это обращение к реквизитам шапки документа через поле Ссылка. Платформа 1С позволяет «разыменовывать» ссылочные поля прямо в тексте запроса. Давайте посмотрим на пример такого запроса:
ВЫБРАТЬ
Инвентаризация.Ссылка.Склад КАК Склад,
Инвентаризация.Номенклатура КАК Номенклатура,
Инвентаризация.Количество КАК Количество,
Инвентаризация.КоличествоОстаток КАК КоличествоОстаток,
Инвентаризация.Цена КАК Цена
ИЗ
Документ.Инвентаризация.Товары КАК Инвентаризация
ГДЕ
Инвентаризация.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Инвентаризация.Ссылка.ВидОперации = &ВыбВид
УПОРЯДОЧИТЬ ПО
Склад
В этом примере мы выбираем данные напрямую из таблицы Документ.Инвентаризация.Товары. Проанализируем ситуацию: когда мы пишем Инвентаризация.Ссылка.Склад, система на уровне СУБД выполняет неявное левое соединение основной таблицы (строк документа) с таблицей шапки документа. Это удобно, но в кругу опытных разработчиков считается «не самым изящным» (или «не кошерным») решением для высоконагруженных систем.
Для повышения прозрачности запроса и контроля над планом его выполнения рекомендуется использовать явные соединения. Если нам нужны только те строки, у которых гарантированно заполнен склад и документ соответствует критериям, лучше применить ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Это позволяет оптимизатору СУБД более эффективно построить план выборки.
Разберем по шагам создание такого запроса:
Ссылка.
ВЫБРАТЬ
ДокШапка.Склад КАК Склад,
ДокТовары.Номенклатура,
ДокТовары.Количество,
ДокТовары.Цена
ИЗ
Документ.Инвентаризация.Товары КАК ДокТовары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Инвентаризация КАК ДокШапка
ПО ДокТовары.Ссылка = ДокШапка.Ссылка
ГДЕ
ДокШапка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И ДокШапка.ВидОперации = &ВыбВид
УПОРЯДОЧИТЬ ПО
Склад
Использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ гарантирует, что в выборку попадут только те строки, для которых существует актуальный документ. Это также избавляет от лишних проверок на NULL, которые могут возникнуть при левом соединении.
Если документов в базе сотни тысяч, то соединение огромной таблицы строк (Товары) с таблицей шапок может работать медленно, так как фильтр (по дате или складу) применяется уже после или во время соединения. Выясним причину: СУБД приходится анализировать слишком много связей. Чтобы ускорить процесс, проанализируем ситуацию и применим временные таблицы.
Сначала мы выберем только ссылки на документы, подходящие под наши условия, во временную таблицу, а затем соединим её с табличной частью:
// Помещаем ссылки на нужные документы во временную таблицу
ВЫБРАТЬ
Инв.Ссылка КАК Ссылка,
Инв.Склад КАК Склад
ПОМЕСТИТЬ ВТ_Документы
ИЗ
Документ.Инвентаризация КАК Инв
ГДЕ
Инв.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Инв.ВидОперации = &ВыбВид;
////////////////////////////////////////////////////////////////////////////////
// Выбираем данные из табличной части, используя подготовленный список ссылок
ВЫБРАТЬ
ВТ.Склад,
Товары.Номенклатура,
Товары.Количество,
Товары.Цена
ИЗ
ВТ_Документы КАК ВТ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Инвентаризация.Товары КАК Товары
ПО ВТ.Ссылка = Товары.Ссылка
Почему это быстрее? Во-первых, временная таблица будет содержать гораздо меньше записей, чем вся таблица документов. Во-вторых, соединение происходит по индексированному полю Ссылка, что является самой быстрой операцией в 1С. Этот метод настоятельно рекомендуется при разработке сложных отчетов.
В сообщении форума справедливо отмечено, что если целью является построение отчета, то тянуть данные напрямую из документов — не всегда верное архитектурное решение. Рассмотрим подробнее, когда стоит использовать регистры:
Инвентаризация делает движения по регистру (например, ИнвентаризацияВТорговыхТочках или ТоварыНаСкладах), то данные в регистре уже содержат информацию о складе (в качестве измерения).Однако стоит учитывать специфику: в некоторых конфигурациях (например, 1С:ERP или КА 2) документ "Инвентаризация товаров" сам по себе не делает движений по регистрам остатков, а является лишь основанием для документов "Списание недостач" или "Оприходование излишков". В таком случае обращение к табличной части документа — единственный способ получить данные о "плановых" показателях инвентаризации.
При работе с запросами к табличным частям обратите внимание на следующие моменты:
Склад в шапке документа. Если по этому полю часто выполняются отборы или сортировки, индексация существенно ускорит запросы.ВидОперации), это работает быстро. Если же ВидОперации — это справочник, убедитесь, что он заполнен корректно во всех документах выборки.Подводя итог, можно сказать: для простых задач достаточно прямого обращения через Ссылка.Склад, но для профессиональной разработки и стабильной скорости работы системы всегда выбирайте вариант с явным соединением или временными таблицами. Это обеспечит масштабируемость вашего кода и отсутствие проблем с производительностью в будущем.