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

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

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

Проблема: Почему ДвиженияССубконто работают медленно?

Рассмотрим стандартную ситуацию: нам необходимо получить проводки по конкретному подразделению и счету (например, 20-й счет) с детализацией по субконто. Типовой запрос к РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто выглядит логичным, но на практике он генерирует крайне тяжелый SQL-код.

Проанализируем, что происходит "под капотом" системы:

  1. Порционная выборка (Batching): Система 1С часто разбивает запрос к этой таблице на мелкие порции (например, по 1000 строк). Если в итоговой выборке 500 000 записей, SQL-сервер получит 500 последовательных запросов. Время тратится не только на выполнение, но и на сетевое взаимодействие между сервером приложений и СУБД (round-trip).
  2. Соединение с таблицей значений субконто: Физически данные регистра хранятся в основной таблице (измерения и ресурсы) и отдельной таблице значений субконто (_AccRgED). При обращении к СубконтоДт1, СубконтоДт2 и так далее, платформа выполняет несколько LEFT JOIN к таблице значений субконто.
  3. Составные типы данных: Если поля субконто не ограничены конкретным типом, SQL-запрос превращается в "простыню" из соединений со всеми возможными таблицами справочников и документов, которые могут выступать в роли субконто.

Способ №1: Использование таблицы ОборотыДтКт (Рекомендуемый)

Как показывает практика, наиболее эффективным решением является замена ДвиженияССубконто на таблицу ОборотыДтКт. Хотя вторая предназначена для итогов, при установке периодичности в значение Регистратор она позволяет получить детальные записи проводок гораздо быстрее.

Разберем пример оптимизированного запроса. Обратите внимание, что виды субконто мы будем получать не через виртуальную таблицу, а путем левого соединения с табличной частью плана счетов. Это исключает лишнюю нагрузку на движок виртуальных таблиц.


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

Почему это работает быстрее?

Способ №2: Оптимизация через оператор ВЫРАЗИТЬ

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

Рассмотрим пример:


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

При использовании ВЫРАЗИТЬ платформа 1С на уровне SQL-запроса оставляет соединение только с одной конкретной таблицей (например, справочником Номенклатурные группы), вместо десятков соединений со всеми типами из ПВХ. Это существенно снижает количество логических чтений диска.

Способ №3: Фильтрация во временных таблицах

Проанализируем еще одну архитектурную проблему. Виртуальные таблицы иногда игнорируют параметры и пытаются выбрать избыточный объем данных перед фильтрацией. Чтобы этого избежать, разделим задачу на два шага:

  1. Выберем во временную таблицу только ключи записей (Регистратор, НомерСтроки, Период) из физической таблицы регистра, применив все необходимые отборы (Счет, Организация, Подразделение).
  2. Соединим полученную временную таблицу с таблицей ДвиженияССубконто или основной таблицей регистра и таблицей значений субконто.

Пример такого подхода:


// Шаг 1: Получаем идентификаторы нужных проводок
ВЫБРАТЬ
    Рег.Период,
    Рег.Регистратор,
    Рег.НомерСтроки
ПОМЕСТИТЬ втКлючиЗаписей
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Рег
ГДЕ
    Рег.Период МЕЖДУ &Начало И &Конец
    И Рег.СчетКт В (&МассивСчетов)
    И Рег.ПодразделениеКт = &Подразделение;

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

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

Резюме и рекомендации

Подведем итоги нашего анализа. Для ускорения работы с проводками и субконто придерживайтесь следующих правил:

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

← На главную