При разработке интерфейсов на управляемых формах 1С разработчики часто сталкиваются с ситуацией, когда стандартная строка поиска в динамическом списке начинает заметно зависать. Особенно ярко эта проблема проявляется при использовании произвольного запроса, даже если результирующая выборка содержит сравнительно небольшое количество строк (например, несколько тысяч записей).
Разберем причины такого поведения платформы, выясним, почему стандартный поиск работает неэффективно, и рассмотрим проверенные практические способы многократного ускорения фильтрации данных.
Проанализируем механизм работы стандартного поиска платформы 1С. Когда пользователь вводит текст в общую строку поиска динамического списка с произвольным запросом, происходят следующие процессы:
ПОДОБНО "%ТекстПоиска%" для каждого видимого строкового поля. Использование знака процента в начале шаблона делает невозможным использование индексов СУБД (B-Tree индексов), что приводит к полному сканированию таблиц (Table Scan / Index Scan).ОсновнаяТаблица, отключается механизм динамического постраничного считывания, и платформа пытается обработать весь массив данных целиком.Рассмотрим наиболее эффективный способ обхода ограничений стандартного поиска, предложенный на практике. Вместо использования платформенной строки поиска мы организуем поиск через собственное поле ввода и наложение отбора на динамический список по массиву найденных ссылок.
Разберем по шагам реализацию этого механизма:
СтрокаПоиска и выведем его в виде поля ввода.ВСписке.Посмотрим на пример программной реализации установки такого отбора:
&НаКлиенте
Процедура СтрокаПоискаПриИзменении(Элемент)
ВыполнитьПоискПоСтрокеНаСервере(СтрокаПоиска);
КонецПроцедуры
&НаСервере
Процедура ВыполнитьПоискПоСтрокеНаСервере(Знач ТекстПоиска)
// Очищаем предыдущий отбор, если строка поиска пустая
Если ПустаяСтрока(ТекстПоиска) Тогда
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список, "Ссылка", , , Истина, Ложь
);
Возврат;
КонецЕсли;
// Выполняем точечный и быстрый запрос к таблице
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Спр.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Спр
|ГДЕ
| Спр.Наименование ПОДОБНО &ШаблонПоиска";
Запрос.УстановитьПараметр("ШаблонПоиска", "%" + ТекстПоиска + "%");
РезультатЗапроса = Запрос.Выполнить();
МассивСсылок = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
// Накладываем отбор на динамический список через компоновку данных
ПолеОтбора = Новый ПолеКомпоновкиДанных("Ссылка");
// Находим или создаем элемент отбора
ЭлементОтбора = Неопределено;
Для Каждого Элемент Из Список.Отбор.Элементы Цикл
Если Элемент.ЛевоеЗначение = ПолеОтбора Тогда
ЭлементОтбора = Элемент;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЭлементОтбора = Неопределено Тогда
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = ПолеОтбора;
КонецЕсли;
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлементОтбора.ПравоеЗначение = МассивСсылок;
ЭлементОтбора.Использование = Истина;
КонецПроцедуры
Такой подход обеспечивает высокую скорость работы, так как СУБД сначала быстро отбирает первичные ключи по целевой таблице, а динамический список затем мгновенно фильтрует строки по первичному ключу Ссылка с использованием кластерного индекса.
Если нет необходимости разрабатывать собственную панель поиска, рассмотрим оптимизацию стандартных свойств таблицы формы и динамического списка.
Ctrl + F или через контекстное меню), выбрав то поле, по которому действительно нужен отбор. Поиск по одной колонке выполняется значительно быстрее глобального.Проанализируем параметры самого динамического списка в конфигураторе, чтобы вернуть ему возможность эффективной динамической подгрузки данных:
УПОРЯДОЧИТЬ ПО, РАЗЛИЧНЫЕ и ИТОГИ. Сортировку списка необходимо настраивать стандартными средствами списка (в свойствах или через Список.Порядок), а не жестко прописывать в тексте запроса.ВЫБОР КОГДА ... для колонок, по которым предполагается регулярный поиск.Если результирующий набор данных всегда ограничен небольшим объемом (в пределах 3 000 – 5 000 строк), динамический список может быть архитектурно избыточен. В этом случае выгодно полностью отказаться от динамического списка в пользу реквизита формы с типом ТаблицаЗначений (или ДанныеФормыКоллекция):