Как правильно отфильтровать данные и оптимизировать запрос к виртуальной таблице ХозрасчетныйДвиженияССубконто

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

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

Анализ проблемы: почему фильтр по наименованию не работает или замедляет систему

Рассмотрим ситуацию: нам нужно вывести документы списания и суммы, исключив при этом определенные позиции номенклатуры (например, "Дизтопливо" и "Регуляр-92"). Начинающий разработчик может написать условие прямо в параметрах виртуальной таблицы, используя обращение к наименованию через точку:


РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
    &НачалоПериода, 
    &КонецПериода, 
    СубконтоКт1.Наименование <> "Дизтопливо" И СубконтоКт1.Наименование <> "Регуляр-92", 
    , 
) КАК ХозрасчетныйДвиженияССубконто

Такой подход содержит сразу две критические ошибки. Во-первых, сравнение по строковому наименованию в запросах крайне неэффективно. Во-вторых, обращение через точку к полю составного типа (которым является Субконто) заставляет СУБД выполнять множественные соединения (LEFT JOIN) со всеми таблицами, которые могут входить в этот вид субконто. Если в вашем плане видов характеристик десятки типов, SQL-запрос превращается в "монстра", который обрабатывается крайне медленно.

Решение 1: Использование ссылок и параметров вместо строк

Первое правило оптимизации: никогда не сравнивайте данные по наименованию, если можно использовать ссылку. Проанализируем, как это сделать правильно. Сначала необходимо найти нужные элементы справочника в коде 1С, поместить их в массив или параметры, и уже их передавать в запрос.

Важный момент: если вы используете отрицание <>, убедитесь, что логика учитывает пустые значения. Но самое главное — передавайте ссылки.


// В коде 1С:
СписокИсключений = Новый Массив;
СписокИсключений.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Дизтопливо"));
СписокИсключений.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Регуляр-92"));

Запрос.УстановитьПараметр("СписокИсключений", СписокИсключений);

Решение 2: Явное указание Вида Субконто

Это самый важный шаг для ускорения работы виртуальной таблицы ДвиженияССубконто. Поскольку поле Субконто составное, платформе нужно подсказать, данные какого именно типа мы ищем. Если мы добавим условие по ВидСубконто, система поймет, что обращаться нужно только к таблице справочника Номенклатура, игнорируя контрагентов, статьи затрат и прочее.

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


(ВидСубконтоКт1 = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура)
 И НЕ СубконтоКт1 В (&СписокИсключений))

Проанализируем ситуацию: когда мы указываем ВидСубконтоКт1, SQL-оптимизатор может эффективно использовать индексы. Без этого условия запрос может сканировать огромные объемы данных, что и вызывает долгое "раздумье", о котором упоминалось в обсуждении.

Решение 3: Параметры виртуальной таблицы против секции ГДЕ

Выясним причину, по которой фильтрация в секции ГДЕ работает медленнее, чем в параметрах самой таблицы. Разберем механизм работы платформы:

  1. Фильтр в параметрах: Условие накладывается на этапе формирования выборки из базы данных. СУБД сразу отсекает ненужные строки и возвращает только тот результат, который соответствует условию.
  2. Фильтр в ГДЕ: Система сначала выбирает все движения за указанный период (это могут быть миллионы строк), строит временную таблицу в оперативной памяти или на диске сервера, и только после этого начинает "выбрасывать" строки, не подходящие под условие.

Рекомендация: Всегда старайтесь максимально ограничивать выборку именно в параметрах виртуальной таблицы (первый параметр — условие счета, третий параметр — условие субконто).

Дополнительные методы оптимизации

Рассмотрим еще несколько профессиональных приемов, которые помогут сделать ваш запрос "неубиваемым":

  1. Использование временных таблиц: Если список исключаемой номенклатуры очень большой (сотни или тысячи позиций), не передавайте его массивом. Лучше загрузите его во временную таблицу, проиндексируйте поле со ссылкой и используйте условие СубконтоКт1 НЕ В (ВЫБРАТЬ Ссылка ИЗ ВТ_Исключения).
  2. Проблема порядка субконто: Помните, что Субконто1, Субконто2 и т.д. — это порядковые номера на конкретном счете. Если на одном счете номенклатура — это первое субконто, а на другом — второе, ваш запрос по СубконтоКт1 пропустит данные по второму счету. В таких случаях нужно либо жестко ограничивать список счетов в первом параметре таблицы, либо использовать более сложную логику проверки вида субконто.
  3. Актуальность итогов: Проверьте, рассчитаны ли итоги в базе данных. Если период запроса (например, 2023 год) находится за пределами рассчитанных итогов, 1С будет вынуждена обращаться к основной таблице движений, что значительно медленнее работы с виртуальными таблицами.

Итоговый правильный пример запроса

Соберем все рекомендации вместе. Наш запрос должен выглядеть примерно так:


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

Важные моменты: мы использовали ЗНАЧЕНИЕ(...) для указания типа, передали список ссылок через параметр и поместили всё это внутрь параметров виртуальной таблицы. Это обеспечит максимальную скорость выполнения и корректность результата даже на очень больших базах данных.

← На главную