Как оптимизировать процедуру формирования отчета в 1С 7.7 на SQL

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Работа с 1С 7.7 в связке с современными версиями SQL Server (2008, 2012 и выше) часто сопровождается проблемами производительности. Когда объем базы превышает несколько гигабайт, штатные "черные" запросы начинают работать крайне неэффективно, формируя отчеты по 10 и более минут. В этой статье мы рассмотрим комплексный подход к оптимизации: от исправления мелких ошибок в коде до перехода на технологию прямых SQL-запросов.

Анализ и оптимизация штатного механизма запросов

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

  1. Отказ от лишних обращений через "точку": Одной из самых частых причин тормозов является обращение к реквизитам объектов внутри цикла обхода запроса. Например, конструкция Запрос.Товар.Наименование или Запрос.Товар.Артикул заставляет систему выполнять отдельный SQL-запрос за данными каждого объекта. Рекомендуем выносить нужные реквизиты сразу в переменные запроса или получать их один раз, обращаясь к объекту целиком.
  2. Оптимизация условий с пустыми значениями: Вместо вызова функций внутри запроса, таких как Условие (ПустаяСтрока(ТоварнаяГруппа)=0), используем заранее подготовленные переменные. Разберем по шагам:
    
    ПустаяГруппа = ПолучитьПустоеЗначение("Справочник.ТоварныеГруппы");
    // В тексте запроса:
    "Условие (ТоварнаяГруппа <> ПустаяГруппа);"
    
  3. Использование фильтрации в коде вместо условий в запросе: На SQL-версиях 1С 7.7 условие Условие (Номенклатура в СписокТоваров) часто работает крайне медленно из-за особенностей генерации SQL-кода. Проанализируем ситуацию: иногда проще убрать это условие из текста запроса и фильтровать результат уже при обходе группировок:
    
    Если СписокТоваров.НайтиЗначение(Запрос.Товар) = 0 Тогда 
        Продолжить; 
    КонецЕсли;
    
  4. Убираем лишние группировки: Если в отчете не нужны группы справочников, обязательно используем конструкцию Группировка Товар без групп;. Это избавит движок 1С от необходимости проверять иерархию для каждой записи.

Работа с периодическими реквизитами

Если в вашем отчете фигурируют цены или другие периодические значения, выясним причину их долгого получения. Стандартный метод Товар.Цена.Получить(Дата) внутри цикла — это верный способ "повесить" отчет. Рассмотрим подробнее использование объекта Периодический:

Вместо постоянного обращения к справочнику, создадим глобальный объект (или инициализируем его один раз перед циклом) и будем использовать метод ИспользоватьОбъект. Это позволяет 1С кэшировать данные и работать на 25-30% быстрее.


ОбъектПериод = СоздатьОбъект("Периодический");
Пока Запрос.Группировка(1) = 1 Цикл
    ОбъектПериод.ИспользоватьОбъект("Цена", Запрос.Товар);
    ТекЦена = ОбъектПериод.ЗначениеНаДату(ДатаОтчета);
КонецЦикла;

Оптимизация вывода в таблицу (Печатную форму)

Часто время тратится не на получение данных, а на их отрисовку. Посмотрим на примеры того, что замедляет вывод:

Переход на прямые запросы через 1C++

Если штатные средства не дают нужного результата, рассмотрим самый эффективный метод — использование компоненты 1C++ и объекта ODBCRecordSet. Это позволяет выполнять запросы напрямую к таблицам SQL, минуя ограничения движка "семерки".

Разберем пример реализации прямого запроса для получения остатков:


ТекстЗапроса = "
|SELECT
|    Рег.Номенклатура as [Товар $Справочник.Номенклатура],
|    Рег.КоличествоОстаток as Остаток,
|    $Тов.Артикул as Артикул
|FROM
|    $РегистрОстатки.ОстаткиТоваров(:ДатаОтчета~,, 
|        (Номенклатура IN (SELECT Val FROM #СписокТоваров))) as Рег
|INNER JOIN 
|    $Справочник.Номенклатура as Тов ON Тов.ID = Рег.Номенклатура
|";

ЗапросSQL = СоздатьОбъект("ODBCRecordSet");
ЗапросSQL.УложитьСписокОбъектов(ВыбТовары, "#СписокТоваров", "Номенклатура");
ЗапросSQL.УстановитьТекстовыйПараметр("ДатаОтчета", ДатаОтчета);
ТЗ = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);

Преимущества этого метода:

  1. Данные обрабатываются на стороне сервера.
  2. Использование INNER JOIN позволяет моментально связывать таблицы остатков со справочниками.
  3. Возможность использовать конструкцию WITH (NOLOCK), что исключает блокировки таблиц при формировании тяжелых отчетов другими пользователями.

Настройка среды SQL Server

Помимо кода, проанализируем настройки самого сервера. Для 1С 7.7 критически важны следующие параметры:

MAXDOP (Maximum Degree of Parallelism): Для баз 1С 7.7 крайне рекомендуется установить это значение в 1. Движок "семерки" генерирует запросы, которые SQL Server пытается распараллелить, что часто приводит к неоптимальным планам выполнения и взаимным блокировкам (Deadlocks).

Legacy Cardinality Estimation: Если вы используете SQL Server 2014 и выше, попробуйте включить флаг совместимости старой оценки стоимости запросов. Это часто "оживляет" старые запросы 1С, которые стали тормозить после обновления сервера.

Итоги

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

← На главную