Как правильно использовать виртуальные таблицы «Остатки и обороты» для оптимизации запросов в 1С?

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

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

Разберем механизм работы виртуальных таблиц

Прежде всего, проанализируем, что происходит «под капотом» платформы. Виртуальные таблицы не существуют в базе данных SQL в явном виде. Когда мы пишем запрос к таблице РегистрНакопления.Продажи.ОстаткиИОбороты, платформа 1С на лету генерирует сложный SQL-запрос, который обращается к физическим таблицам итогов и таблице движений. Чтобы лучше понимать этот процесс, можно проанализировать SQL сервер глазами 1С-ника, изучая сформированные запросы и ожидания. Если мы не ограничиваем выборку параметрами, система вынуждена пересчитывать данные за весь период существования базы, что приводит к колоссальным нагрузкам. Это ключевой аспект, который затрагивает оптимизация запросов к виртуальным таблицам остатков и оборотов в 1С 8.3.

Рассмотрим основные параметры, которые критически важны для производительности:

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

Выясним причину медленной работы: Фильтр в параметрах против ГДЕ

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

Неправильный подход:


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

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

Правильный подход:


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

Здесь мы передаем условие непосредственно в параметры виртуальной таблицы. В результате SQL-запрос, сформированный платформой, будет содержать фильтр WHERE уже на этапе первичного обращения к таблицам БД. Система прочитает только те данные, которые относятся к нашему складу.

Посмотрим на пример использования временных таблиц для фильтрации

Зачастую условие фильтрации бывает сложным, например, нам нужно отобрать данные по списку номенклатуры, который хранится в массиве или другой таблице значений. В таких случаях мы рекомендуем использование временных таблиц в запросах 1С. Для проектирования и отладки таких выборок отлично подходит консоль запросов с поддержкой пакетных запросов и временных таблиц — есть инструментарий разработчика с консолью запросов и СКД. Это позволяет СУБД построить оптимальный план запроса, используя индексы.

Рассмотрим по шагам реализацию этого метода:

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

Проанализируем пример кода:


// 1. Помещаем список товаров во временную таблицу
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст = 
"ВЫБРАТЬ
|   Товары.Ссылка КАК Товар
|ПОМЕСТИТЬ ВТ_НужныеТовары
|ИЗ
|   &СписокТоваров КАК Товары
|ИНДЕКСИРОВАТЬ ПО
|   Товар";
Запрос.УстановитьПараметр("СписокТоваров", МассивТоваров);
Запрос.Выполнить();

// 2. Используем ВТ в параметрах виртуальной таблицы
Запрос.Текст = 
"ВЫБРАТЬ
|   ОстаткиИОбороты.Товар,
|   ОстаткиИОбороты.КоличествоКонечныйОстаток
|ИЗ
|   РегистрНакопления.Запасы.ОстаткиИОбороты(,, , , Товар В (ВЫБРАТЬ Т.Товар ИЗ ВТ_НужныеТовары КАК Т)) КАК ОстаткиИОбороты";
Результат = Запрос.Выполнить();

Использование конструкции В (ВЫБРАТЬ ...) внутри параметров виртуальной таблицы позволяет 1С передать этот список на уровень SQL, что значительно ускоряет выборку по сравнению с передачей огромного массива напрямую в параметр &Массив.

Разберем по шагам работу с периодичностью

Параметр Периодичность в таблице ОстаткиИОбороты часто игнорируется, хотя он имеет огромное значение. Здесь кроются секреты параметра «Периодичность» и таблицы итогов. Если вам нужно получить остатки на конец каждого месяца, не стоит выбирать данные с периодичностью Регистратор или Период, а потом группировать их.

Посмотрим, как это работает: если вы укажете периодичность Месяц, система будет использовать таблицу итогов, где данные уже агрегированы по месяцам. Это в десятки раз быстрее, чем сканировать таблицу движений. Рассмотрим пример получения динамики остатков:


ВЫБРАТЬ
    Запасы.Период КАК Месяц,
    Запасы.Номенклатура,
    Запасы.КоличествоНачальныйОстаток,
    Запасы.КоличествоКонечныйОстаток
ИЗ
    РегистрНакопления.Запасы.ОстаткиИОбороты(&ДатаНач, &ДатаКон, Месяц, , ) КАК Запасы

В данном примере мы сразу получаем готовый набор данных, разбитый по месяцам, без лишних вычислений на стороне сервера приложений.

Важные моменты при индексации регистров

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

Проанализируем ситуацию: если вы фильтруете таблицу Обороты по реквизиту «Менеджер», который не является измерением и не проиндексирован, SQL будет выполнять Table Scan (полное сканирование таблицы), что нивелирует все преимущества использования параметров виртуальной таблицы. Для того чтобы упростить работу разработчика в таких ситуациях, полезно применять инструменты для быстрого анализа данных.

Подведем итоги и сформируем правила работы

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

  1. Всегда ограничивайте НачалоПериода и КонецПериода.
  2. Используйте максимально крупную Периодичность, допустимую вашей задачей.
  3. Никогда не используйте ГДЕ для фильтрации по измерениям — только параметры виртуальной таблицы.
  4. Для больших списков значений используйте МенеджерВременныхТаблиц и индексированные временные таблицы внутри параметров.
  5. Следите за индексами: фильтрация эффективна только по индексированным полям.

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

← На главную