При работе с крупными базами данных "1С:Предприятие 8" производительность запросов к регистрам бухгалтерии становится критически важной. Часто возникает задача получить остатки не по всем счетам и товарам, а по конкретному списку номенклатуры, который уже отобран во временную таблицу. В этой статье мы разберем по шагам, как трансформировать неоптимальный запрос в высокопроизводительный механизм, используя возможности виртуальных таблиц.
Рассмотрим типичную ситуацию: у нас есть временная таблица ТабНоменклатура, и нам нужно получить по ней остатки. Начинающие разработчики часто используют ЛЕВОЕ СОЕДИНЕНИЕ временной таблицы с виртуальной таблицей остатков. Проанализируем пример такого кода:
// ТабНоменклатура - номенклатура для запроса остатков
ВЫБРАТЬ
Таб0.Номенклатура
ПОМЕСТИТЬ ТабНоменклатура
ИЗ
Таб0
СГРУППИРОВАТЬ ПО
Таб0.Номенклатура;
// Получаем остатки через соединение
ВЫБРАТЬ
Остатки.Субконто3.Код КАК СкладКод,
Остатки.КоличествоОстаток КАК Остатки,
Остатки.Субконто1.Код КАК НоменклатураКод
ИЗ
ТабНоменклатура КАК ТабНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(, Счет В ИЕРАРХИИ (&ВыбСчет), , Субконто3 В (&Склады)) КАК Остатки
ПО ТабНоменклатура.Номенклатура = Остатки.Субконто1
Выясним причину неоптимальности: в данном случае виртуальная таблица Остатки сначала рассчитает данные по всем товарам на указанных складах и счетах, и только потом СУБД выполнит соединение с вашей временной таблицей. Если в справочнике 100 000 товаров, а вам нужно всего 1 000, система выполнит огромный объем лишней работы.
Правильный подход заключается в том, чтобы "пробросить" список номенклатуры внутрь самой виртуальной таблицы. Это позволит платформе 1С и SQL-серверу ограничить выборку на самом раннем этапе.
Для этого мы воспользуемся конструкцией В (ВЫБРАТЬ ... ИЗ ВТ) прямо во втором параметре (Условие) виртуальной таблицы. Рассмотрим исправленный код:
ВЫБРАТЬ
Остатки.Субконто3.Код КАК СкладКод,
Остатки.КоличествоОстаток КАК Остатки,
Остатки.Субконто1.Код КАК НоменклатураКод
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(
,
Счет В ИЕРАРХИИ (&ВыбСчет),
,
Субконто1 В (ВЫБРАТЬ Т.Номенклатура ИЗ ТабНоменклатура КАК Т)
И Субконто3 В (&Склады)
) КАК Остатки
Такой подход заставляет СУБД использовать индексы регистра по полям субконто, что в разы ускоряет выполнение запроса при больших объемах данных.
Одной из скрытых проблем регистра бухгалтерии является неопределенность порядка субконто. На одном счете "Номенклатура" может быть первым субконто, на другом — вторым. Если мы просто пишем Субконто1, запрос может отработать некорректно или медленно.
Рассмотрим решение: передачу третьего параметра виртуальной таблицы — ВидыСубконто. Мы создаем массив, содержащий ссылки на ПВХ ВидыСубконтоХозрасчетные.Номенклатура и ВидыСубконтоХозрасчетные.Склады.
При использовании этого параметра платформа жестко фиксирует, что Субконто1 — это номенклатура, а Субконто2 — склад (в соответствии с порядком в массиве), независимо от настроек конкретного счета. Это исключает лишние соединения с таблицами значений субконто на уровне SQL.
Когда мы используем временную таблицу в условии В (ВЫБРАТЬ...), крайне важно обеспечить быстрый поиск по ней. Если список номенклатуры содержит сотни или тысячи записей, обязательно добавьте индекс. Проанализируем пример создания проиндексированной ВТ:
ВЫБРАТЬ
Таб0.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ТабНоменклатура
ИЗ
&ИсходныеДанные КАК Таб0
СГРУППИРОВАТЬ ПО
Таб0.Номенклатура
ИНДЕКСИРОВАТЬ ПО
Номенклатура;
Без индекса СУБД может прибегнуть к сканированию всей временной таблицы для каждой строки основного запроса, что нивелирует всю выгоду от использования параметров виртуальной таблицы.
Поля Субконто1, Субконто2 имеют составной тип данных. При обращении к свойствам этих полей (например, Субконто1.Код) в SQL-запросе создается множество соединений (JOIN) со всеми возможными таблицами справочников, входящих в этот тип.
Рекомендация: всегда используйте ВЫРАЗИТЬ. Это позволяет SQL-серверу обращаться напрямую к таблице конкретного справочника.
ВЫБРАТЬ
ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.Номенклатура).Код КАК НоменклатураКод,
ВЫРАЗИТЬ(Остатки.Субконто3 КАК Справочник.Склады).Код КАК СкладКод,
Остатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(
&Период,
Счет В ИЕРАРХИИ (&ВыбСчет),
&МассивВидовСубконто,
Субконто1 В (ВЫБРАТЬ Т.Номенклатура ИЗ ТабНоменклатура КАК Т)
) КАК Остатки
Подводя итог, выделим основные правила написания производительного запроса к регистру бухгалтерии:
ГДЕ или через СОЕДИНЕНИЕ после получения всех остатков. Всегда передавайте условия во второй параметр виртуальной таблицы.СубконтоN и ускоряет работу SQL.ВЫРАЗИТЬ для полей субконто в итоговой выборке.Соблюдение этих правил гарантирует, что ваш код будет работать стабильно быстро даже при значительном росте объема данных в информационной базе.