Почему медленно работает запрос к виртуальной таблице ОстаткиИОбороты?

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

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

Разберем исходный код запроса

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


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

Причина №1: Актуальность рассчитанных итогов

Первое, на что следует обратить внимание, — это разница во времени выполнения между маем и июнем. Если за май запрос выполняется 5 секунд, а за июнь — 15 минут, то с вероятностью 99% проблема в рассчитанных итогах.

В системе 1С итоги хранятся помесячно в специальных физических таблицах. Если итоги рассчитаны по 31 мая, то при формировании отчета за май система просто берет готовые цифры из таблицы итогов. Однако, если мы запрашиваем данные за июнь, а итоги за него еще не рассчитаны, системе приходится динамически вычислять остатки, сканируя все записи основной таблицы движений (проводок) от последней точки актуальных итогов до конца июня. Если проводок много, это вызывает колоссальные задержки.

Что нужно сделать: Проверить через «Управление итогами» (в режиме 1С:Предприятие или через встроенные обработки), установлена ли дата рассчитанных итогов на конец июня или более позднюю дату. Убедитесь, что итоги включены и актуальны.

Причина №2: Использование периодичности Регистратор

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

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

Причина №3: Обращение через точку (неявные соединения)

Проанализируем поле ХозрасчетныйОстаткиИОбороты.Субконто1.Наименование. Поскольку Субконто1 в регистре бухгалтерии имеет составной тип данных (может быть Номенклатурой, Основным средством и т.д.), обращение через точку заставляет SQL-сервер выполнять левое соединение со всеми возможными таблицами справочников, которые входят в этот составной тип.

Решение: Если вы точно знаете, что Субконто1 — это справочник Номенклатура, используйте оператор ВЫРАЗИТЬ. Это подскажет системе, к какой конкретно таблице нужно обратиться, и исключит лишние соединения.


ВЫБРАТЬ
    ВЫРАЗИТЬ(ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Справочник.Номенклатура).Наименование КАК Субконто1Наименование
...

Еще лучше — вовсе отказаться от получения наименования в запросе. Получайте только ссылку (Субконто1), а представление или наименование выводите средствами системы компоновки данных (СКД) или при заполнении печатной формы.

Причина №4: Оптимизация фильтра В ИЕРАРХИИ

Использование В ИЕРАРХИИ в параметрах виртуальной таблицы — еще одно «узкое место». Платформа вынуждена сначала определить все дочерние элементы для всех групп в списке &парамСписокТМЦ, и только потом передавать этот огромный список в SQL-запрос.

Рассмотрим более эффективный подход:

  1. Создадим временную таблицу и поместим в нее все элементы нужной иерархии.
  2. Проиндексируем эту таблицу.
  3. В основном запросе будем использовать условие В (ВЫБРАТЬ ... ИЗ ВременнаяТаблица).

Это позволит оптимизатору SQL-сервера построить более эффективный план выполнения запроса через INNER JOIN.

Причина №5: Параметры виртуальной таблицы и Виды Субконто

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

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


// Пример задания видов субконто в параметрах
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
    &НачПериода,
    &КонПериода,
    Регистратор,
    ,
    Счет В ИЕРАРХИИ (&парамСписокСчетов),
    &МассивВидовСубконто, // ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура и т.д.
    Организация В (&парамОрганизация) И Субконто1 В (&СписокТМЦ)
)

Причина №6: Избыточная группировка и упорядочивание

В запросе присутствует секция СГРУППИРОВАТЬ ПО. При использовании периодичности Регистратор в виртуальной таблице данные уже приходят сгруппированными по регистратору, периоду и измерениям. Дополнительная группировка в основном тексте запроса заставляет SQL-сервер выполнять повторную агрегацию, что требует значительных ресурсов CPU и временной памяти (TempDB).

Также обратите внимание на АВТОУПОРЯДОЧИВАНИЕ. Эта инструкция часто добавляет в ORDER BY поля, которые вам не нужны (например, внутренние идентификаторы или коды), что замедляет сортировку. Лучше всегда указывать явную сортировку только по тем полям, которые необходимы для логики отчета.

Итоги и рекомендации

Подведем итог. Чтобы ваш запрос работал стабильно быстро независимо от выбранного месяца, выполните следующие шаги:

  1. Проверьте итоги: Это база. Если итоги не рассчитаны, никакая оптимизация кода не поможет.
  2. Используйте ВЫРАЗИТЬ: Всегда типизируйте поля субконто при обращении к их реквизитам.
  3. Минимизируйте периодичность: Если можно обойтись без Регистратор, используйте периодичность Месяц или Период.
  4. Передавайте Виды Субконто: Это критически важно для правильного использования индексов в бухгалтерских регистрах.
  5. Избегайте В ИЕРАРХИИ в основном запросе: Предварительно выгружайте иерархию во временную таблицу.
  6. Используйте объект Граница: Для параметров &КонПериода всегда передавайте Новый Граница(КонецДня(ВашаДата), ВидГраницы.Включая), чтобы данные на последнюю секунду периода попадали корректно.

Применяя эти методы, вы не только ускорите текущий запрос, но и обеспечите стабильную работу системы при росте объема данных в будущем.

← На главную