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