Как ускорить поиск по части артикула в 1С и поможет ли полнотекстовый поиск?

Программист 1С v8.3 (Обычные формы)
← На главную

В процессе разработки и сопровождения баз данных на платформе 1С:Предприятие 8.3, особенно в конфигурациях на обычных формах, разработчики часто сталкиваются с проблемой производительности при поиске в справочнике Номенклатура. Когда объем данных в справочнике превышает десятки или сотни тысяч записей, стандартный поиск по части артикула начинает заметно «тормозить». В этой статье мы подробно разберем, поможет ли включение механизма полнотекстового поиска (ППС), выясним причины низкой скорости стандартных запросов и рассмотрим альтернативные методы оптимизации.

Проблема стандартного поиска через оператор ПОДОБНО

Разберем ситуацию, когда поиск реализован программно через запрос или через стандартную настройку «Способ поиска: По любой части» в свойствах поля ввода. В этом случае система генерирует SQL-запрос с использованием оператора LIKE и масок % с обеих сторон искомого выражения (например, ПОДОБНО "%123%").

Проанализируем, почему это происходит медленно. Основная причина кроется в архитектуре индексов СУБД (MS SQL Server, PostgreSQL и др.). Традиционные B-Tree индексы, которые использует 1С, эффективно работают только в том случае, если мы ищем точное совпадение или начало строки (например, ПОДОБНО "123%"). Если же символ процента стоит в начале шаблона, СУБД не может использовать индекс и вынуждена выполнять полное сканирование таблицы (Full Table Scan). На больших справочниках это приводит к длительному ожиданию и высокой нагрузке на дисковую подсистему сервера.

Поможет ли включение полнотекстового поиска (ППС)?

Существует мнение, что включение полнотекстового поиска мгновенно решит проблему скорости. Однако здесь есть критически важный нюанс. Рассмотрим, как работает механизм ППС в 1С. Он индексирует данные на уровне слов. Чтобы поиск сработал, искомая строка должна быть началом слова.

Выясним причину, по которой поиск по артикулу может не сработать в ППС:

  1. Отсутствие разделителей: Если артикул записан как АВ09834868, то поиск по строке 868 через ППС ничего не найдет, так как цифры 868 находятся в середине «слова».
  2. Наличие разделителей: Если артикул имеет вид АВ-098-348-68, то дефис может выступать разделителем. В этом случае поиск по 348 сработает, так как это будет считаться началом отдельного слова в индексе.
  3. Ограничения масок: В стандартном полнотекстовом поиске 1С маска * (звездочка) поддерживается только в конце запроса (например, 868*). Конструкция *868, которая могла бы найти подстроку в середине слова, платформой не поддерживается.

Таким образом, простое включение галочки «Использовать полнотекстовый поиск» даст результат только в том случае, если ваши пользователи ищут артикул всегда с начала или если артикулы разделены специальными символами.

Стратегия оптимизации: Поиск в три итерации

Если нам необходимо обеспечить быстрый поиск и при этом сохранить возможность нахождения подстроки в середине артикула, рассмотрим эффективный алгоритм «трех итераций». Вместо того чтобы сразу выполнять тяжелый запрос с ПОДОБНО "%Текст%", мы будем сужать область поиска постепенно.

Разберем этот алгоритм по шагам:

  1. Итерация 1: Точное совпадение. Сначала ищем артикул на полное равенство. Это самый быстрый запрос, использующий индекс. Если результат найден — поиск прекращается.
  2. Итерация 2: Поиск по началу строки. Если точное совпадение не найдено, выполняем запрос ПОДОБНО "Текст%". СУБД всё еще может эффективно использовать индекс (Index Seek или Index Scan по диапазону).
  3. Итерация 3: Поиск по части строки. Только если первые два шага не дали результата (или дали слишком мало строк), мы запускаем «тяжелый» запрос ПОДОБНО "%Текст%".

Посмотрим на пример реализации такого поиска в коде 1С:


// Пример реализации многошагового поиска
Функция НайтиНоменклатуруПоАртикулу(ТекстПоиска)
    
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ТекстРавно", ТекстПоиска);
    Запрос.УстановитьПараметр("ТекстПодобноНачало", ТекстПоиска + "%");
    Запрос.УстановитьПараметр("ТекстПодобноВезде", "%" + ТекстПоиска + "%");
    
    // 1. Пытаемся найти точное совпадение
    Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул = &ТекстРавно";
    Результат = Запрос.Выполнить().Выгрузить();
    
    Если Результат.Количество() > 0 Тогда
        Возврат Результат;
    КонецЕсли;
    
    // 2. Ищем по началу артикула (эффективно по индексу)
    Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул ПОДОБНО &ТекстПодобноНачало";
    Результат = Запрос.Выполнить().Выгрузить();
    
    Если Результат.Количество() > 0 Тогда
        Возврат Результат;
    КонецЕсли;
    
    // 3. Крайний случай - поиск по всей строке (медленно)
    Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул ПОДОБНО &ТекстПодобноВезде";
    Возврат Запрос.Выполнить().Выгрузить();
    
КонецФункции

Использование дополнительных реквизитов для ППС

Для того чтобы полнотекстовый поиск всё же начал «видеть» середину артикула, мы можем применить хитрость, которую часто используют опытные разработчики. Проанализируем ситуацию: ППС ищет по словам. Значит, нам нужно превратить части артикула в слова.

Рассмотрим шаги реализации:

  1. Создадим в справочнике Номенклатура скрытый реквизит АртикулДляПоиска (тип Строка, неограниченная длина или достаточная для хранения суффиксов).
  2. Включим для этого реквизита свойство Полнотекстовый поиск: Использовать.
  3. В модуле объекта в процедуре ПередЗаписью напишем код, который будет разбивать артикул на части и записывать их через пробел. Например, для артикула 12345 в поле поиска запишем 12345 2345 345 45 5.

Теперь, если пользователь введет 345, ППС найдет это слово в реквизите АртикулДляПоиска, так как для него это будет отдельное слово, начинающееся на 345.

Настройка регламентных заданий

Если мы решили использовать ППС (как для стандартных механизмов, так и для дополнительных реквизитов), важно помнить о поддержании индекса в актуальном состоянии. Выясним, какие настройки необходимо проверить в консоли администрирования или через РегламентныеЗадания:

Без правильно настроенного обновления индекса, новые артикулы не будут попадать в результаты поиска, что вызовет недовольство пользователей.

Заключение и рекомендации

Подведем итоги нашего исследования. Механизм полнотекстового поиска — мощный инструмент, но он не является «серебряной пулей» для поиска по произвольной подстроке внутри артикула без предварительной подготовки данных.

Основные выводы:

  1. Для мгновенного ускорения поиска по началу строки убедитесь, что реквизит Артикул индексирован (свойство Индексировать в метаданных).
  2. Если поиск по любой части критичен, используйте стратегию «трех итераций» в запросах, чтобы не нагружать СУБД без необходимости.
  3. Для максимальной производительности ППС при поиске «середины» артикула используйте метод создания дополнительного поискового реквизита с суффиксами.
  4. Всегда ограничивайте количество возвращаемых результатов через оператор ПЕРВЫЕ, чтобы не перегружать память сервера и клиентского приложения.

Проанализировав данные методы, мы можем выбрать наиболее подходящий под конкретные требования бизнеса и объем данных в вашей информационной базе.

← На главную