Разработка и Конфигурация · 10 мин
Как оптимизировать код в 1С: практическое руководство
Конкретные приёмы оптимизации кода 1С: устранение запросов в циклах, работа с индексами, оптимизация СКД и обмена данными, поиск узких мест через замеры производительности.
Медленный код в 1С почти всегда имеет конкретную причину: лишние обращения к базе данных, неэффективные запросы, обработка больших объёмов данных в памяти или блокировки при параллельной работе пользователей. Оптимизация начинается не с переписывания кода «наугад», а с точного поиска узкого места — иначе есть риск потратить время на участок, который и так работает быстро.
Основные инструменты диагностики уже встроены в платформу: замер производительности в конфигураторе, технологический журнал, план запроса на стороне СУБД. Умея ими пользоваться, вы сможете за один сеанс найти 80% реальных проблем производительности.
Ниже разобраны практические приёмы: как найти медленный участок, как переписать запросы, что делать с циклами и обменами данными, и как проверить, что оптимизация действительно дала результат.
Как найти узкое место: замер производительности
Первый шаг — запустить замер производительности в конфигураторе: меню «Отладка» → «Замер производительности». После этого воспроизведите проблемную операцию (проведение документа, формирование отчёта) и остановите замер. Платформа покажет таблицу вызовов с количеством вызовов, чистым и суммарным временем каждой строки кода.
Обращайте внимание не только на самые «тяжёлые» строки, но и на строки с аномально большим количеством вызовов. Например, функция получения цены, вызванная 50 000 раз по 5 мс, даст 250 секунд — и именно её нужно оптимизировать, даже если каждый отдельный вызов выглядит безобидно.
Для серверных проблем, которые не воспроизводятся в отладке, используйте технологический журнал: настройте сбор событий DBMSSQL или DBPOSTGRS с длительностью, чтобы увидеть самые долгие запросы и их контекст. На стороне СУБД план выполнения запроса покажет, используются ли индексы или выполняется полное сканирование таблицы.
- 1Включите замер производительности в конфигураторе
- 2Воспроизведите медленную операцию на данных, близких к рабочим
- 3Отсортируйте результат по суммарному времени и по количеству вызовов
- 4Выделите 1–3 самых затратных участка
- 5Исправьте один участок и повторите замер для сравнения
Устранение запросов в цикле
Самая частая ошибка — выполнение запроса внутри цикла обхода данных. Каждый запрос — это обращение к СУБД с накладными расходами на соединение, разбор и выполнение. Тысяча итераций с запросом внутри превращается в тысячу обращений к базе.
Правильный подход — собрать все нужные данные одним запросом до начала цикла. Используйте соединения таблиц, временные таблицы или пакетные запросы, чтобы получить всё необходимое за одно обращение, а затем обращайтесь к результату в памяти.
Для быстрого поиска в выборке используйте соответствие или таблицу значений с индексом, а не повторный запрос. Если нужно по каждой строке документа получить остатки — выберите остатки по всем позициям сразу через условие «Номенклатура В (&СписокНоменклатуры)».
// Плохо: запрос в цикле
Для Каждого Строка Из ТаблицаТоваров Цикл
Запрос.УстановитьПараметр("Номенклатура", Строка.Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
КонецЦикла;
// Хорошо: один запрос до цикла
Запрос.УстановитьПараметр("СписокТоваров", ТаблицаТоваров.ВыгрузитьКолонку("Номенклатура"));
Результат = Запрос.Выполнить().Выгрузить();
Результат.Индексы.Добавить("Номенклатура");
Для Каждого Строка Из ТаблицаТоваров Цикл
Найденные = Результат.НайтиСтроки(Новый Структура("Номенклатура", Строка.Номенклатура));
КонецЦикла;Оптимизация запросов и индексов
Запрос должен выбирать только те поля и строки, которые реально нужны. Конструкция «ВЫБРАТЬ *» или выборка всех записей справочника с последующей фильтрацией в коде заставляет СУБД читать и передавать лишние данные. Условия отбора должны находиться в запросе, а не в цикле после выборки.
Проверьте, что по полям соединений и условий существуют индексы. Для регистров сведений и накопления критичен порядок измерений: отбор по измерению, стоящему первым, работает быстрее. При соединении виртуальных таблиц регистров с другими таблицами накладывайте отборы на виртуальную таблицу через параметры, а не через соединение — иначе СУБД сначала построит всю виртуальную таблицу.
Избегайте функций над полями в условиях (например, «ПОДСТРОКА(Наименование, 1, 3) = "АБВ"») — такие условия отключают использование индекса. То же относится к соединениям по полям разных типов и к условиям «ИЛИ» между разными таблицами.
Работа с объектами и большими объёмами данных
Обращение к реквизитам объекта через точку после получения ссылки — скрытый источник запросов. Конструкция «Ссылка.Наименование» в цикле вызывает обращение к базе при каждом обращении к новому объекту. Если нужны реквизиты множества ссылок, получите их одним запросом.
Конструктор «Новый Запрос» создание запроса внутри цикла тоже стоит вынести наружу: создайте объект запроса один раз, а в цикле меняйте только параметры — хотя, как сказано выше, лучше вообще убрать запрос из цикла.
При обработке больших объёмов (сотни тысяч записей) не загружайте всё в память одной таблицей значений, если можно обработать порциями. Используйте выборку запроса с обходом, пакетную обработку с разбивкой по диапазонам, а для длительных операций — фоновые задания, чтобы не блокировать сеанс пользователя.
Оптимизация отчётов на СКД
Медленный отчёт чаще всего страдает из-за запроса в наборе данных. Проверьте его теми же методами: отборы должны передаваться в параметры виртуальных таблиц, соединения — по индексированным полям, вычисляемые поля — без функций над полями условий.
Важный нюанс СКД — автозаполнение и состав выбранных полей. Если в настройках отчёта выбрано больше полей, чем нужно пользователю, СКД всё равно их вычислит. Ограничьте состав полей в варианте отчёта и отключайте неиспользуемые ресурсы.
Также проверьте роли: если у пользователя нет прав на часть данных, механизм ограничения доступа (RLS) добавляет к запросу сложные соединения, которые могут радикально замедлить отчёт. Для регламентных отчётов рассмотрите выполнение от имени привилегированного фонового задания с последующим показом результата.
Блокировки и параллельная работа
Если код работает быстро в тесте, но «виснет» при одновременной работе пользователей, проблема в блокировках. Длительные транзакции проведения, изменение данных вне транзакции, чтение с последующей записью тех же таблиц — типичные причины взаимных ожиданий.
Сокращайте время транзакции: выполняйте тяжёлые расчёты до начала транзакции записи, а внутри неё оставляйте только запись. Используйте управляемые блокировки данных с явным указанием полей — это сужает диапазон блокируемых записей.
Для регистров включите разделение итогов там, где это применимо, и следите, чтобы документы записывали движения в порядке, согласованном между разными видами документов — это снижает вероятность взаимоблокировок.
Проверка результата оптимизации
Оптимизация без повторного замера — это гадание. После каждого изменения повторите замер производительности на тех же данных и сравните время ключевых операций. Фиксируйте цифры «до» и «после» — это защитит от субъективных оценок и поможет отловить регрессии.
Проверяйте не только скорость, но и корректность: оптимизированный запрос должен возвращать те же данные. Особенно внимательно относитесь к замене соединений, добавлению отборов и изменению порядка обхода — здесь легко потерять строки с пустыми значениями.
Как проверить результат
Стало заметно ниже на тех же данных
Время не изменилось или выросло — узкое место в другом месте
Один-два запроса вместо запроса на каждую итерацию
Число запросов пропорционально числу строк
Данные совпадают с результатом до оптимизации
Пропали строки или изменились суммы
Нет ожиданий на блокировках в техножурнале
Растут события TLOCK и TDEADLOCK
Частые вопросы
С чего начать, если база тормозит «везде и сразу»?
Начните не с кода, а с инфраструктуры: проверьте загрузку сервера СУБД, объём памяти, настройки СУБД и наличие актуальной статистики по таблицам. Если инфраструктура в порядке, соберите технологический журнал за час пиковой нагрузки и найдите самые частые и долгие запросы — они укажут на конкретные механизмы конфигурации.
Ускорит ли работу перевод кода на сервер?
Сам по себе — нет. Перенос выполнения на сервер убирает сетевые вызовы между клиентом и сервером, что помогает при большом числе серверных вызовов из клиентского кода. Но неэффективный запрос на сервере останется неэффективным. Сначала оптимизируйте логику, затем смотрите на распределение кода между клиентом и сервером.
Нужно ли всегда заменять запросы в цикле на один большой запрос?
Почти всегда да, но есть предел: если запрос становится чрезмерно сложным (десятки соединений, огромные временные таблицы), он может работать медленнее и потреблять много памяти. В таких случаях разбивайте обработку на порции: один запрос на партию данных, а не на каждую строку.
Помогает ли обновление платформы производительности?
Новые версии платформы регулярно включают оптимизации механизмов, но конкретный эффект предсказать нельзя. Обновление стоит планировать как отдельную задачу с тестированием, а не как средство лечения конкретной медленной операции — её причина почти всегда в прикладном коде или структуре данных.
Как ускорить проведение документов без переписывания логики?
Проверьте три вещи: нет ли в обработчиках запросов в циклах, не выполняются ли тяжёлые расчёты внутри транзакции записи и включён ли режим проведения «оперативный/неоперативный» осознанно. Также посмотрите, не снимаются ли итоги у регистров и нет ли обменов данными, срабатывающих при каждом проведении.
Что делать, если узкое место — в типовом коде конфигурации на поддержке?
Не правьте типовой модуль напрямую: это усложнит обновления. Используйте расширение конфигурации с переопределением проблемного метода или, если точка расширения недоступна, вынесите оптимизированную логику в свой вызов до/после типового механизма. Зафиксируйте проблему замером — это пригодится при обращении к разработчику конфигурации.
Что важно запомнить
Оптимизация кода 1С — это цикл «замер → исправление одного узкого места → повторный замер». Чаще всего ускорение дают устранение запросов в циклах, корректные индексы и отборы на уровне запроса, сокращение транзакций и порционная обработка больших данных. Любые изменения сначала проверяйте на копии базы.