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