При разработке сложных отчетов в системе 1С, особенно когда дело касается регистров бухгалтерии, программисты часто сталкиваются с необходимостью отфильтровать данные по конкретному типу субконто. Поскольку поле Субконто имеет составной тип данных, выбор неправильного метода фильтрации может привести к катастрофическому падению производительности и полному сканированию огромных таблиц итогов. Разберем подробно, какой из инструментов платформы работает эффективнее всего и почему.
Рассмотрим ситуацию, когда разработчик пытается использовать конструкцию В ИЕРАРХИИ для проверки типа, передавая в нее пустую ссылку нужного справочника. С точки зрения производительности — это самый худший вариант из возможных. Проанализируем причины:
В ИЕРАРХИИ предназначен для рекурсивного обхода дерева групп и элементов. Даже если вы передаете одну ссылку (или пустую ссылку), платформа инициирует механизмы проверки иерархии.ОстаткиИОбороты) использование этого оператора приводит к тому, что условия не могут быть эффективно проброшены внутрь физических таблиц на уровне СУБД.Конструкция ТИПЗНАЧЕНИЯ(Субконто1) = ТИП(Справочник.ФизическиеЛица) выглядит логично, но имеет свои нюансы. Разберем, как это работает «под капотом»:
В базе данных SQL составной тип (например, Субконто1) хранится в нескольких колонках. Обычно это идентификатор типа (_Subkonto1_TRef) и идентификатор ссылки (_Subkonto1_RRef). Когда мы используем ТИПЗНАЧЕНИЯ, платформа сравнивает значение в колонке _TRef.
Однако в старых версиях платформы или в сложных соединениях такая конструкция могла приводить к неявным соединениям с таблицами описания метаданных, что замедляло запрос. На современных версиях платформы 8.3 этот метод работает быстрее, чем В ИЕРАРХИИ, но все еще может уступать более специализированным операторам.
Проанализируем использование ключевого слова ССЫЛКА. Пример кода:
ГДЕ
Субконто1 ССЫЛКА Справочник.ФизическиеЛица
Это стандартный и очень эффективный способ. На уровне SQL он транслируется в максимально простую проверку одной колонки _TRef. Основные преимущества:
Index Seek (поиск по индексу), а не Index Scan (сканирование всего индекса).Посмотрим на один из самых «хитрых» и быстрых способов, который часто применяют опытные разработчики для оптимизации виртуальных таблиц. Это использование функции ВЫРАЗИТЬ совместно с проверкой на NULL или пустую ссылку. Рассмотрим пример:
ВЫБРАТЬ
Регистр.Субконто1,
Регистр.СуммаОстаток
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(
&Период,
Счет = &Счет,
,
ВЫРАЗИТЬ(Субконто1 КАК Справочник.ФизическиеЛица) <> ЗНАЧЕНИЕ(Справочник.ФизическиеЛица.ПустаяСсылка)
) КАК Регистр
Или еще более эффективный вариант для фильтрации именно по типу:
ГДЕ
ВЫРАЗИТЬ(Субконто1 КАК Справочник.ФизическиеЛица) ЕСТЬ НЕ NULL
Выясним, почему это работает быстро. Когда вы применяете ВЫРАЗИТЬ в параметрах виртуальной таблицы, вы явно указываете платформе, к какой физической таблице справочника (через поле ссылки) нужно обращаться. Если тип Субконто1 не соответствует указанному, результат приведения будет NULL. Этот метод позволяет платформе максимально сузить выборку еще на этапе формирования исходного SQL-запроса к таблицам итогов.
Проанализируем итоги и выстроим иерархию методов от самого быстрого к самому медленному:
ВЫРАЗИТЬ(... КАК ...) ЕСТЬ НЕ NULL или ССЫЛКА. Они работают напрямую с идентификаторами типов в индексах.ТИПЗНАЧЕНИЯ(...) = ТИП(...). Работает хорошо, но менее универсально в плане оптимизации планов запросов.В ИЕРАРХИИ. Категорически не рекомендуется использовать для проверки типов из-за огромных накладных расходов.Рассмотрим ситуацию из практики: если аналитика распределена по разным справочникам, и вам постоянно приходится фильтровать их в виртуальных таблицах, возможно, стоит пересмотреть структуру учета. Как отмечалось в обсуждении, иногда эффективнее:
Счет.Помните, что фильтрация по Измерению (Счет) всегда будет на порядки быстрее, чем фильтрация по Характеристике (Субконто), так как Счет — это ведущее поле во всех индексах регистров бухгалтерии. Если вы ограничите выборку конкретными счетами, SQL-серверу вообще не придется анализировать типы субконто для тех записей, которые заведомо не относятся к делу.