К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как оптимизировать код в 1С: практическое руководство

Конкретные приёмы оптимизации кода 1С: устранение запросов в циклах, работа с индексами, оптимизация СКД и обмена данными, поиск узких мест через замеры производительности.

Медленный код в 1С почти всегда имеет конкретную причину: лишние обращения к базе данных, неэффективные запросы, обработка больших объёмов данных в памяти или блокировки при параллельной работе пользователей. Оптимизация начинается не с переписывания кода «наугад», а с точного поиска узкого места — иначе есть риск потратить время на участок, который и так работает быстро.

Основные инструменты диагностики уже встроены в платформу: замер производительности в конфигураторе, технологический журнал, план запроса на стороне СУБД. Умея ими пользоваться, вы сможете за один сеанс найти 80% реальных проблем производительности.

Ниже разобраны практические приёмы: как найти медленный участок, как переписать запросы, что делать с циклами и обменами данными, и как проверить, что оптимизация действительно дала результат.

Как найти узкое место: замер производительности

Первый шаг — запустить замер производительности в конфигураторе: меню «Отладка» → «Замер производительности». После этого воспроизведите проблемную операцию (проведение документа, формирование отчёта) и остановите замер. Платформа покажет таблицу вызовов с количеством вызовов, чистым и суммарным временем каждой строки кода.

Обращайте внимание не только на самые «тяжёлые» строки, но и на строки с аномально большим количеством вызовов. Например, функция получения цены, вызванная 50 000 раз по 5 мс, даст 250 секунд — и именно её нужно оптимизировать, даже если каждый отдельный вызов выглядит безобидно.

Для серверных проблем, которые не воспроизводятся в отладке, используйте технологический журнал: настройте сбор событий DBMSSQL или DBPOSTGRS с длительностью, чтобы увидеть самые долгие запросы и их контекст. На стороне СУБД план выполнения запроса покажет, используются ли индексы или выполняется полное сканирование таблицы.

Порядок поиска узкого места
  1. 1
    Включите замер производительности в конфигураторе
  2. 2
    Воспроизведите медленную операцию на данных, близких к рабочим
  3. 3
    Отсортируйте результат по суммарному времени и по количеству вызовов
  4. 4
    Выделите 1–3 самых затратных участка
  5. 5
    Исправьте один участок и повторите замер для сравнения

Устранение запросов в цикле

Самая частая ошибка — выполнение запроса внутри цикла обхода данных. Каждый запрос — это обращение к СУБД с накладными расходами на соединение, разбор и выполнение. Тысяча итераций с запросом внутри превращается в тысячу обращений к базе.

Правильный подход — собрать все нужные данные одним запросом до начала цикла. Используйте соединения таблиц, временные таблицы или пакетные запросы, чтобы получить всё необходимое за одно обращение, а затем обращайтесь к результату в памяти.

Для быстрого поиска в выборке используйте соответствие или таблицу значений с индексом, а не повторный запрос. Если нужно по каждой строке документа получить остатки — выберите остатки по всем позициям сразу через условие «Номенклатура В (&СписокНоменклатуры)».

bsl
// Плохо: запрос в цикле
Для Каждого Строка Из ТаблицаТоваров Цикл
    Запрос.УстановитьПараметр("Номенклатура", Строка.Номенклатура);
    Выборка = Запрос.Выполнить().Выбрать();
КонецЦикла;

// Хорошо: один запрос до цикла
Запрос.УстановитьПараметр("СписокТоваров", ТаблицаТоваров.ВыгрузитьКолонку("Номенклатура"));
Результат = Запрос.Выполнить().Выгрузить();
Результат.Индексы.Добавить("Номенклатура");
Для Каждого Строка Из ТаблицаТоваров Цикл
    Найденные = Результат.НайтиСтроки(Новый Структура("Номенклатура", Строка.Номенклатура));
КонецЦикла;

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

Запрос должен выбирать только те поля и строки, которые реально нужны. Конструкция «ВЫБРАТЬ *» или выборка всех записей справочника с последующей фильтрацией в коде заставляет СУБД читать и передавать лишние данные. Условия отбора должны находиться в запросе, а не в цикле после выборки.

Проверьте, что по полям соединений и условий существуют индексы. Для регистров сведений и накопления критичен порядок измерений: отбор по измерению, стоящему первым, работает быстрее. При соединении виртуальных таблиц регистров с другими таблицами накладывайте отборы на виртуальную таблицу через параметры, а не через соединение — иначе СУБД сначала построит всю виртуальную таблицу.

Избегайте функций над полями в условиях (например, «ПОДСТРОКА(Наименование, 1, 3) = "АБВ"») — такие условия отключают использование индекса. То же относится к соединениям по полям разных типов и к условиям «ИЛИ» между разными таблицами.

Работа с объектами и большими объёмами данных

Обращение к реквизитам объекта через точку после получения ссылки — скрытый источник запросов. Конструкция «Ссылка.Наименование» в цикле вызывает обращение к базе при каждом обращении к новому объекту. Если нужны реквизиты множества ссылок, получите их одним запросом.

Конструктор «Новый Запрос» создание запроса внутри цикла тоже стоит вынести наружу: создайте объект запроса один раз, а в цикле меняйте только параметры — хотя, как сказано выше, лучше вообще убрать запрос из цикла.

При обработке больших объёмов (сотни тысяч записей) не загружайте всё в память одной таблицей значений, если можно обработать порциями. Используйте выборку запроса с обходом, пакетную обработку с разбивкой по диапазонам, а для длительных операций — фоновые задания, чтобы не блокировать сеанс пользователя.

Типичные ошибки
01
Запрос внутри цикла — тысячи обращений к СУБД вместо одного
02
Получение реквизитов через Ссылка.Реквизит в цикле — скрытые запросы на каждую строку
03
Выборка всех полей и строк с фильтрацией в коде — лишний трафик и память
04
Поиск в таблице значений методом Найти без индекса — полный перебор на каждой итерации
05
Пересчёт итогов регистра внутри транзакции проведения — рост времени блокировок

Оптимизация отчётов на СКД

Медленный отчёт чаще всего страдает из-за запроса в наборе данных. Проверьте его теми же методами: отборы должны передаваться в параметры виртуальных таблиц, соединения — по индексированным полям, вычисляемые поля — без функций над полями условий.

Важный нюанс СКД — автозаполнение и состав выбранных полей. Если в настройках отчёта выбрано больше полей, чем нужно пользователю, СКД всё равно их вычислит. Ограничьте состав полей в варианте отчёта и отключайте неиспользуемые ресурсы.

Также проверьте роли: если у пользователя нет прав на часть данных, механизм ограничения доступа (RLS) добавляет к запросу сложные соединения, которые могут радикально замедлить отчёт. Для регламентных отчётов рассмотрите выполнение от имени привилегированного фонового задания с последующим показом результата.

Блокировки и параллельная работа

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

Сокращайте время транзакции: выполняйте тяжёлые расчёты до начала транзакции записи, а внутри неё оставляйте только запись. Используйте управляемые блокировки данных с явным указанием полей — это сужает диапазон блокируемых записей.

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

Проверка результата оптимизации

Оптимизация без повторного замера — это гадание. После каждого изменения повторите замер производительности на тех же данных и сравните время ключевых операций. Фиксируйте цифры «до» и «после» — это защитит от субъективных оценок и поможет отловить регрессии.

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

Контрольные точки

Как проверить результат

Время операции в замере производительности
Норма

Стало заметно ниже на тех же данных

Тревожный признак

Время не изменилось или выросло — узкое место в другом месте

Количество обращений к СУБД
Норма

Один-два запроса вместо запроса на каждую итерацию

Тревожный признак

Число запросов пропорционально числу строк

Результат обработки
Норма

Данные совпадают с результатом до оптимизации

Тревожный признак

Пропали строки или изменились суммы

Работа при параллельных сеансах
Норма

Нет ожиданий на блокировках в техножурнале

Тревожный признак

Растут события TLOCK и TDEADLOCK

Частые вопросы

С чего начать, если база тормозит «везде и сразу»?

Начните не с кода, а с инфраструктуры: проверьте загрузку сервера СУБД, объём памяти, настройки СУБД и наличие актуальной статистики по таблицам. Если инфраструктура в порядке, соберите технологический журнал за час пиковой нагрузки и найдите самые частые и долгие запросы — они укажут на конкретные механизмы конфигурации.

Ускорит ли работу перевод кода на сервер?

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

Нужно ли всегда заменять запросы в цикле на один большой запрос?

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

Помогает ли обновление платформы производительности?

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

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

Проверьте три вещи: нет ли в обработчиках запросов в циклах, не выполняются ли тяжёлые расчёты внутри транзакции записи и включён ли режим проведения «оперативный/неоперативный» осознанно. Также посмотрите, не снимаются ли итоги у регистров и нет ли обменов данными, срабатывающих при каждом проведении.

Что делать, если узкое место — в типовом коде конфигурации на поддержке?

Не правьте типовой модуль напрямую: это усложнит обновления. Используйте расширение конфигурации с переопределением проблемного метода или, если точка расширения недоступна, вынесите оптимизированную логику в свой вызов до/после типового механизма. Зафиксируйте проблему замером — это пригодится при обращении к разработчику конфигурации.

Итог

Что важно запомнить

Оптимизация кода 1С — это цикл «замер → исправление одного узкого места → повторный замер». Чаще всего ускорение дают устранение запросов в циклах, корректные индексы и отборы на уровне запроса, сокращение транзакций и порционная обработка больших данных. Любые изменения сначала проверяйте на копии базы.