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