Разработка и поддержка крупных информационных систем на платформе 1С:Предприятие неизбежно сталкивает нас с вопросами оптимизации производительности. Один из классических вопросов, который возникает у разработчиков при обнаружении медленной работы форм: «Можно ли просто проиндексировать реквизит, не сломается ли что-то в системе, и как это скажется на работе?».
В этой статье мы подробно разберем, как устроен механизм индексирования в 1С, детально проанализируем причины медленной работы динамических списков, выясним, почему отсутствие отбора может парадоксально замедлять систему, и рассмотрим пошаговые сценарии оптимизации запросов на примере работы с задачами.
Прежде чем установить заветную галочку «Индексировать» в свойствах реквизита конфигуратора, давайте проанализируем ситуацию и разберемся, что физически происходит на уровне базы данных (MS SQL Server, PostgreSQL или др.).
Индекс в СУБД — это вспомогательная структура (чаще всего сбалансированное дерево или B-Tree), предназначенная для ускорения поиска строк. Однако создание нового индекса имеет свою «цену»:
Поэтому индексировать реквизиты «на всякий случай» категорически не рекомендуется. Делать это нужно только на основе точечного анализа планов запросов и замеров производительности.
Посмотрим на пример простого запроса к таблице задач, который вызывает затруднения у автора темы:
ВЫБРАТЬ
ЗадачаЗадача.Ссылка,
ЗадачаЗадача.ДатаИсполнения,
ЗадачаЗадача.Автор,
ЗадачаЗадача.РезультатВыполнения,
ЗадачаЗадача.Исполнитель
ИЗ
Задача.Задача КАК ЗадачаЗадача
Казалось бы, запрос элементарный. Но почему он может выполняться критически долго в динамическом списке? Разберем механизмы платформы по шагам.
Рассмотрим подробнее поведение динамического списка. Автор темы столкнулся с парадоксом: при включенном отборе по реквизиту список открывается долго, но если этот отбор убрать совсем, то время ожидания становится еще больше.
Это классическое поведение для динамических списков (ДС), работающих с большими таблицами. Дело в механизме порционной выборки:
Ссылка или Дата).ДатаИсполнения или Автор), СУБД все равно придется просканировать всю гигантскую таблицу задач, чтобы выполнить сортировку в памяти (Sort) и выдать первые 45 строк.Для решения проблем с динамическими списками стандартного индексирования реквизита часто бывает недостаточно. Нам важно понимать разницу между тремя режимами свойства «Индексировать» в 1С:
Автор = &Параметр).[Реквизит] + [Ссылка].Почему вариант с дополнительным упорядочиванием критически важен для динамического списка? Динамический список всегда неявно упорядочивает данные по уникальному ключу (обычно по полю Ссылка), чтобы гарантировать стабильность прокрутки (пейджинга). Если мы выбираем вариант «с дополнительным упорядочиванием», СУБД сможет за одно действие и применить отбор по реквизиту, и сразу получить данные в нужном порядке сортировки (по ссылке), избегая тяжелой операции сортировки в памяти на стороне сервера СУБД.
Выясним причину, по которой простой запрос в консоли запросов выполняется медленно. Очень часто проблема кроется не в самом запросе, а в механизме RLS (Row-Level Security):
LEFT JOIN) к таблицам прав доступа, ролей исполнителей и групп физических лиц.Задачи в 1С имеют свои архитектурные особенности, которые напрямую влияют на скорость выполнения запросов:
РезультатВыполнения в запросе автора. Очень часто его создают с типом «Строка неограниченной длины». В СУБД такие поля хранятся как LOB (Large Object - BLOB/NVARCHAR(MAX)) отдельно от основной таблицы. Вывод такого поля непосредственно в динамический список заставляет СУБД совершать огромное количество операций по чтению отдельных блоков данных с диска, что драматически снижает скорость прокрутки и открытия списка.Проанализируем ситуацию и составим четкий план действий для решения проблемы медленного открытия формы:
Перед внесением изменений убедимся, что дело именно в запросе динамического списка. Запустим замер производительности в конфигураторе, откроем форму списка и проверим, какая именно строка кода или системное событие занимает больше всего времени. Обратим внимание на серверное время выполнения метода при открытии формы.
Уберем из состава полей динамического списка реквизит РезультатВыполнения (строку неограниченной длины). Проверим, насколько быстрее стал работать список. Если пользователю необходимо видеть результат выполнения задачи, выведем его в отдельное текстовое поле на форме, которое будет заполняться только при активизации строки списка (событие ПриАктивизацииСтроки), выполняя легкий точечный запрос к базе данных.
Выполним запрос под учетной записью администратора с полными правами. Если скорость работы значительно выросла, необходимо пересмотреть настройки ограничений доступа (RLS) и оптимизировать шаблоны ограничений для объекта метаданных «Задача».
Если поиск действительно выполняется по конкретному реквизиту (например, по реквизиту связи), установим для него в конфигураторе свойство «Индексировать» в значение «Индексировать с дополнительным упорядочиванием». Это позволит оптимизировать как фильтрацию, так и сортировку данных внутри динамического списка.
Проверим свойства динамического списка на форме:
Если мы добавили индекс в конфигураторе, но СУБД продолжает выполнять запрос медленно, возможно, оптимизатор использует устаревшие данные. Необходимо выполнить регламентные операции на сервере СУБД (MS SQL Server или PostgreSQL):
UPDATE STATISTICS для MS SQL или ANALYZE для PostgreSQL).Систематическое применение этих шагов позволит не только решить локальную проблему с долго открывающейся формой задач, но и существенно повысить общую отзывчивость интерфейса системы для конечных пользователей.