В практике разработки на платформе 1С программисты часто сталкиваются с ситуацией, когда при первом формировании отчета или запуске обработки запрос выполняется десятки секунд (например, 30 секунд), а при повторных вызовах — всего за 3 секунды или даже быстрее. Проанализируем физические причины такого поведения системы и рассмотрим комплексы мер по оптимизации.
Различие во времени выполнения между первым («холодным») и последующими («горячими») запусками обусловлено несколькими ключевыми механизмами работы СУБД и сервера приложений 1С:
Даже если повторный запрос выполняется за 3 секунды благодаря кэшу, это не означает, что текст запроса оптимален. Высокое число чтений при холодном старте указывает на несовершенство структуры запроса. Проанализируем типовые ошибки и варианты их исправления.
1. Устранение разыменования полей через точку (неявных соединений)
Рассмотрим фрагмент кода, где в секции условий используется обращение через точку к реквизиту ссылочного поля:
И НЕ Мед_ТалоныПриема.Регистратор.НеВключатьВРеестры
Такое обращение заставляет платформу 1С формировать неявное левое соединение со ВСЕМИ возможными таблицами документов, которые могут выступать в качестве типе составной ссылки Регистратор. Если тип составной или содержит множество документов, это существенно усложняет план SQL и приводит к избыточным чтениям.
Для исправления заменим неявное обращение на явное соединение с конкретной таблицей документа и применим ограничение типа с помощью ССЫЛКА:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Мед_ТалоныПриема.Регистратор КАК Регистратор
ПОМЕСТИТЬ втТалоныПриемаИсх
ИЗ
РегистрСведений.Мед_ТалоныПриема КАК Мед_ТалоныПриема
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Мед_СтатТалон КАК ТотСамыйДокумент
ПО Мед_ТалоныПриема.Регистратор = ТотСамыйДокумент.Ссылка
И (ТотСамыйДокумент.НеВключатьВРеестры)
ЛЕВОЕ СОЕДИНЕНИЕ втИсключаемыеТалоны КАК втИсключаемыеТалоны
ПО Мед_ТалоныПриема.Регистратор = втИсключаемыеТалоны.Регистратор
ГДЕ
Мед_ТалоныПриема.Период МЕЖДУ &ДатаНачала И &ДатаКонца
И Мед_ТалоныПриема.Регистратор ССЫЛКА Документ.Мед_СтатТалон
И Мед_ТалоныПриема.ИФ = 2
И Мед_ТалоныПриема.СМООМС = &Организация
И втИсключаемыеТалоны.Регистратор ЕСТЬ NULL
2. Индексирование временных таблиц
Если временная таблица используется далее в соединениях с другими таблицами (особенно с большими объемами данных), ее необходимо проиндексировать по полям связи. Это позволяет СУБД применять эффективные алгоритмы соединения (например, Index Seek вместо сканирования):
ВЫБРАТЬ РАЗЛИЧНЫЕ
Мед_ИспользованиеДокументовВРеестрах.Документ КАК Регистратор
ПОМЕСТИТЬ втИсключаемыеТалоны
ИЗ
РегистрСведений.Мед_ИспользованиеДокументовВРеестрах КАК Мед_ИспользованиеДокументовВРеестрах
ГДЕ
Мед_ИспользованиеДокументовВРеестрах.Период >= &ДатаКонцаМинус6Месяца
И Мед_ИспользованиеДокументовВРеестрах.ВидСтрахования <> ЗНАЧЕНИЕ(Перечисление.Мед_ВидыСтрахования.ПустаяСсылка)
И Мед_ИспользованиеДокументовВРеестрах.Документ ССЫЛКА Документ.Мед_СтатТалон
ИНДЕКСИРОВАТЬ ПО
Регистратор
Разберем системные настройки и механизмы, которые помогут минимизировать задержки при первых вызовах отчетов пользователями в начале рабочего дня.
Buffer Pool. В ОС Windows Server включим право Lock Pages in Memory («Закрепление страниц в памяти») для учетной записи службы SQL Server.SQL Server Profiler / Extended Events. Основное внимание уделяем показателю логических чтений (Logical Reads) и операторам сканирования (Clustered Index Scan / Table Scan) в плане выполнения.