Как увеличить быстродействие запроса к остаткам регистра бухгалтерии?

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

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача получения остатков по счетам с высокой аналитической нагрузкой, таким как 60.01 "Расчеты с поставщиками и подрядчиками" или 62.01 "Расчеты с покупателями и заказчиками". Когда объем данных в информационной базе растет, простые запросы к виртуальным таблицам начинают работать медленно. Разберем детально, как можно оптимизировать исходный код и на какие архитектурные нюансы следует обратить внимание.

1. Оптимизация на уровне написания кода и параметров запроса

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

Использование ссылок вместо кодов счетов. В исходном коде используется условие Счет.Код = "60.01". Это крайне неэффективно, так как заставляет систему выполнять дополнительное соединение с таблицей плана счетов и осуществлять поиск по строковому полю. Вместо этого следует передавать готовую ссылку на счет или использовать предопределенное значение прямо в тексте запроса. Разберем, как это реализовать:


// Вариант 1: Передача параметра
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.РасчетыСПоставщиками);

// Вариант 2: Использование конструкции ЗНАЧЕНИЕ в тексте запроса
| РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.РасчетыСПоставщиками), , Организация = &Организация)

Отказ от выгрузки в таблицу значений. Метод Выгрузить() копирует все данные из результата запроса в оперативную память сервера приложений. Если остатков много, это вызывает значительное потребление ресурсов и задержки. Проанализируем ситуацию: гораздо эффективнее работать с результатом запроса через выборку, используя метод Выбрать(). Это позволяет считывать данные порциями (курсором), что значительно снижает нагрузку на RAM.


// Вместо: Выборка = Запрос.Выполнить().Выгрузить();
// Используем:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    // Обработка данных
КонецЦикла;

2. Работа с субконто и виртуальными таблицами

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

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


ВидыСубконто = Новый Массив;
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты);
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры);

// Передаем массив вторым параметром виртуальной таблицы
Запрос.Текст = "ВЫБРАТЬ ... ИЗ РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, Счет = &Счет, &ВидыСубконто, Организация = &Организация)";
Запрос.УстановитьПараметр("ВидыСубконто", ВидыСубконто);

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

3. Глубокая оптимизация: Платформа и SQL

Иногда программных правок недостаточно, и проблема кроется в структуре хранения данных или работе оптимизатора СУБД. Разберем продвинутые методы ускорения.

Хранение субконто в таблице движений (Платформа 8.3.15+). В современных версиях 1С реализована важная возможность. В свойствах Плана счетов можно включить опцию «Данные субконто в таблице движений». Проанализируем эффект: после включения и реструктуризации значения субконто начинают дублироваться непосредственно в основной таблице итогов. Это устраняет необходимость в JOIN при выполнении запроса, что дает колоссальный прирост производительности на высокооборотистых счетах.

Объект «Граница» для параметра Период. При получении остатков на дату важно понимать, как система обрабатывает эту точку во времени. Если передать просто Дата, система может тратить время на уточнение состава движений внутри секунды. Рекомендуется использовать объект Граница:


ГраницаПериода = Новый Граница(КонецДня(ПараметрДата), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", ГраницаПериода);

Индексация субконто. В конфигураторе для конкретного Плана видов характеристик (Виды субконто) для часто используемых аналитик (Контрагенты, Номенклатура) следует установить признак «Индексировать». Это создаст дополнительные индексы в SQL, позволяя выполнять поиск Index Seek вместо полного сканирования Index Scan.

4. Проблемы оптимизатора SQL на больших данных

Рассмотрим ситуацию, когда запрос по-прежнему работает медленно на счетах 60.01 или 62.01. Выясним причину: при получении неоперативных остатков (на прошлую дату) SQL-сервер может ошибочно выбрать некластерный индекс по счету, который не содержит сумм, и в итоге переключиться на полное сканирование таблицы. Чтобы этого избежать, можно применить следующие подходы:

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

Альтернативный путь: Если задача позволяет, рассмотрите возможность использования регистров накопления (например, "Взаиморасчеты с поставщиками"). Регистры накопления по своей структуре проще бухгалтерского регистра (в них нет двойной записи и сложных таблиц субконто), поэтому запросы к ним всегда будут выполняться быстрее. Если же требуется именно сверка с бухгалтерией, используйте все вышеперечисленные методы оптимизации в комплексе.

← На главную