В процессе разработки и сопровождения баз данных на платформе 1С:Предприятие 8.3, особенно в конфигурациях на обычных формах, разработчики часто сталкиваются с проблемой производительности при поиске в справочнике Номенклатура. Когда объем данных в справочнике превышает десятки или сотни тысяч записей, стандартный поиск по части артикула начинает заметно «тормозить». В этой статье мы подробно разберем, поможет ли включение механизма полнотекстового поиска (ППС), выясним причины низкой скорости стандартных запросов и рассмотрим альтернативные методы оптимизации.
Разберем ситуацию, когда поиск реализован программно через запрос или через стандартную настройку «Способ поиска: По любой части» в свойствах поля ввода. В этом случае система генерирует SQL-запрос с использованием оператора LIKE и масок % с обеих сторон искомого выражения (например, ПОДОБНО "%123%").
Проанализируем, почему это происходит медленно. Основная причина кроется в архитектуре индексов СУБД (MS SQL Server, PostgreSQL и др.). Традиционные B-Tree индексы, которые использует 1С, эффективно работают только в том случае, если мы ищем точное совпадение или начало строки (например, ПОДОБНО "123%"). Если же символ процента стоит в начале шаблона, СУБД не может использовать индекс и вынуждена выполнять полное сканирование таблицы (Full Table Scan). На больших справочниках это приводит к длительному ожиданию и высокой нагрузке на дисковую подсистему сервера.
Существует мнение, что включение полнотекстового поиска мгновенно решит проблему скорости. Однако здесь есть критически важный нюанс. Рассмотрим, как работает механизм ППС в 1С. Он индексирует данные на уровне слов. Чтобы поиск сработал, искомая строка должна быть началом слова.
Выясним причину, по которой поиск по артикулу может не сработать в ППС:
АВ09834868, то поиск по строке 868 через ППС ничего не найдет, так как цифры 868 находятся в середине «слова».АВ-098-348-68, то дефис может выступать разделителем. В этом случае поиск по 348 сработает, так как это будет считаться началом отдельного слова в индексе.* (звездочка) поддерживается только в конце запроса (например, 868*). Конструкция *868, которая могла бы найти подстроку в середине слова, платформой не поддерживается.Таким образом, простое включение галочки «Использовать полнотекстовый поиск» даст результат только в том случае, если ваши пользователи ищут артикул всегда с начала или если артикулы разделены специальными символами.
Если нам необходимо обеспечить быстрый поиск и при этом сохранить возможность нахождения подстроки в середине артикула, рассмотрим эффективный алгоритм «трех итераций». Вместо того чтобы сразу выполнять тяжелый запрос с ПОДОБНО "%Текст%", мы будем сужать область поиска постепенно.
Разберем этот алгоритм по шагам:
ПОДОБНО "Текст%". СУБД всё еще может эффективно использовать индекс (Index Seek или Index Scan по диапазону).ПОДОБНО "%Текст%".Посмотрим на пример реализации такого поиска в коде 1С:
// Пример реализации многошагового поиска
Функция НайтиНоменклатуруПоАртикулу(ТекстПоиска)
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТекстРавно", ТекстПоиска);
Запрос.УстановитьПараметр("ТекстПодобноНачало", ТекстПоиска + "%");
Запрос.УстановитьПараметр("ТекстПодобноВезде", "%" + ТекстПоиска + "%");
// 1. Пытаемся найти точное совпадение
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул = &ТекстРавно";
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 0 Тогда
Возврат Результат;
КонецЕсли;
// 2. Ищем по началу артикула (эффективно по индексу)
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул ПОДОБНО &ТекстПодобноНачало";
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 0 Тогда
Возврат Результат;
КонецЕсли;
// 3. Крайний случай - поиск по всей строке (медленно)
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул ПОДОБНО &ТекстПодобноВезде";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Для того чтобы полнотекстовый поиск всё же начал «видеть» середину артикула, мы можем применить хитрость, которую часто используют опытные разработчики. Проанализируем ситуацию: ППС ищет по словам. Значит, нам нужно превратить части артикула в слова.
Рассмотрим шаги реализации:
Номенклатура скрытый реквизит АртикулДляПоиска (тип Строка, неограниченная длина или достаточная для хранения суффиксов).Полнотекстовый поиск: Использовать.ПередЗаписью напишем код, который будет разбивать артикул на части и записывать их через пробел. Например, для артикула 12345 в поле поиска запишем 12345 2345 345 45 5.Теперь, если пользователь введет 345, ППС найдет это слово в реквизите АртикулДляПоиска, так как для него это будет отдельное слово, начинающееся на 345.
Если мы решили использовать ППС (как для стандартных механизмов, так и для дополнительных реквизитов), важно помнить о поддержании индекса в актуальном состоянии. Выясним, какие настройки необходимо проверить в консоли администрирования или через РегламентныеЗадания:
Без правильно настроенного обновления индекса, новые артикулы не будут попадать в результаты поиска, что вызовет недовольство пользователей.
Подведем итоги нашего исследования. Механизм полнотекстового поиска — мощный инструмент, но он не является «серебряной пулей» для поиска по произвольной подстроке внутри артикула без предварительной подготовки данных.
Основные выводы:
Артикул индексирован (свойство Индексировать в метаданных).ПЕРВЫЕ, чтобы не перегружать память сервера и клиентского приложения.Проанализировав данные методы, мы можем выбрать наиболее подходящий под конкретные требования бизнеса и объем данных в вашей информационной базе.