Работа с 1С 7.7 в связке с современными версиями SQL Server (2008, 2012 и выше) часто сопровождается проблемами производительности. Когда объем базы превышает несколько гигабайт, штатные "черные" запросы начинают работать крайне неэффективно, формируя отчеты по 10 и более минут. В этой статье мы рассмотрим комплексный подход к оптимизации: от исправления мелких ошибок в коде до перехода на технологию прямых SQL-запросов.
Прежде чем полностью переписывать код, проанализируем текущие конструкции штатного запроса. Даже небольшие изменения в синтаксисе могут дать существенный прирост скорости.
Запрос.Товар.Наименование или Запрос.Товар.Артикул заставляет систему выполнять отдельный SQL-запрос за данными каждого объекта. Рекомендуем выносить нужные реквизиты сразу в переменные запроса или получать их один раз, обращаясь к объекту целиком.Условие (ПустаяСтрока(ТоварнаяГруппа)=0), используем заранее подготовленные переменные. Разберем по шагам:
ПустаяГруппа = ПолучитьПустоеЗначение("Справочник.ТоварныеГруппы");
// В тексте запроса:
"Условие (ТоварнаяГруппа <> ПустаяГруппа);"
Условие (Номенклатура в СписокТоваров) часто работает крайне медленно из-за особенностей генерации SQL-кода. Проанализируем ситуацию: иногда проще убрать это условие из текста запроса и фильтровать результат уже при обходе группировок:
Если СписокТоваров.НайтиЗначение(Запрос.Товар) = 0 Тогда
Продолжить;
КонецЕсли;
Группировка Товар без групп;. Это избавит движок 1С от необходимости проверять иерархию для каждой записи.Если в вашем отчете фигурируют цены или другие периодические значения, выясним причину их долгого получения. Стандартный метод Товар.Цена.Получить(Дата) внутри цикла — это верный способ "повесить" отчет. Рассмотрим подробнее использование объекта Периодический:
Вместо постоянного обращения к справочнику, создадим глобальный объект (или инициализируем его один раз перед циклом) и будем использовать метод ИспользоватьОбъект. Это позволяет 1С кэшировать данные и работать на 25-30% быстрее.
ОбъектПериод = СоздатьОбъект("Периодический");
Пока Запрос.Группировка(1) = 1 Цикл
ОбъектПериод.ИспользоватьОбъект("Цена", Запрос.Товар);
ТекЦена = ОбъектПериод.ЗначениеНаДату(ДатаОтчета);
КонецЦикла;
Часто время тратится не на получение данных, а на их отрисовку. Посмотрим на примеры того, что замедляет вывод:
ПрисоединитьСекцию: Это очень "дорогая" операция. Если структура отчета позволяет, лучше заранее подготовить несколько вариантов строк в макете и использовать ВывестиСекцию.Таб.Область().РамкаСправа(3) в цикле сильно нагружают графический движок. Попробуем оформить все визуальные элементы непосредственно в макете таблицы.Если штатные средства не дают нужного результата, рассмотрим самый эффективный метод — использование компоненты 1C++ и объекта ODBCRecordSet. Это позволяет выполнять запросы напрямую к таблицам SQL, минуя ограничения движка "семерки".
Разберем пример реализации прямого запроса для получения остатков:
ТекстЗапроса = "
|SELECT
| Рег.Номенклатура as [Товар $Справочник.Номенклатура],
| Рег.КоличествоОстаток as Остаток,
| $Тов.Артикул as Артикул
|FROM
| $РегистрОстатки.ОстаткиТоваров(:ДатаОтчета~,,
| (Номенклатура IN (SELECT Val FROM #СписокТоваров))) as Рег
|INNER JOIN
| $Справочник.Номенклатура as Тов ON Тов.ID = Рег.Номенклатура
|";
ЗапросSQL = СоздатьОбъект("ODBCRecordSet");
ЗапросSQL.УложитьСписокОбъектов(ВыбТовары, "#СписокТоваров", "Номенклатура");
ЗапросSQL.УстановитьТекстовыйПараметр("ДатаОтчета", ДатаОтчета);
ТЗ = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);
Преимущества этого метода:
INNER JOIN позволяет моментально связывать таблицы остатков со справочниками.WITH (NOLOCK), что исключает блокировки таблиц при формировании тяжелых отчетов другими пользователями.Помимо кода, проанализируем настройки самого сервера. Для 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 — это всегда баланс между исправлением кода и настройкой системного окружения. Начните с замера производительности: если основное время уходит на Запрос.Выполнить(), переходите к прямым запросам. Если же тормозит обход результатов — оптимизируйте обращения к реквизитам и вывод в печатную форму.