Как быстро найти артикул, скрытый внутри строки с наименованием, при больших объемах данных?

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

Представим типичную задачу: необходимо загрузить данные из внешнего файла, где артикул товара «спрятан» внутри строки с наименованием без каких-либо разделителей. При этом в базе данных 400 000 артикулов, а во входящем файле 100 000 строк. Обычный перебор с использованием функции СтрНайти() потребует 40 миллиардов итераций, что приведет к катастрофическим затратам времени. В этой статье мы разберем наиболее эффективные алгоритмические подходы для решения данной проблемы.

Проблема производительности: почему стандартные методы не работают

Стандартный подход Цикл по СтрокамФайла -> Цикл по АртикуламБазы -> СтрНайти(Наименование, Артикул) имеет сложность O(N * M). На больших объемах это означает, что выполнение задачи может занять десятки часов. Нам необходимо сократить количество сравнений или использовать структуры данных, которые позволяют выполнять поиск за константное или логарифмическое время.

Метод 1: Использование регулярных выражений (платформа 8.3.23+)

Если ваша платформа поддерживает регулярные выражения на уровне встроенного языка, мы можем скомпилировать «мега-запрос», объединяющий множество артикулов через оператор «ИЛИ» (символ |). Рассмотрим логику этого процесса: мы разбиваем массив артикулов на группы (например, по 500-1000 штук) и для каждой группы создаем паттерн.

Проанализируем пример реализации на языке Python, который легко переносится на встроенный язык 1С с использованием новых объектов РегулярноеВыражение:


// Пример логики формирования регулярного выражения
ТекстРегулярки = "(артикул1)|(артикул2)|(артикул3)...";
РегВыражение = Новый РегулярноеВыражение(ТекстРегулярки, ПараметрыРегулярногоВыражения.Многострочный);

Для Каждого СтрокаТекста Из СписокНаименований Цикл
    Результат = РегВыражение.Найти(СтрокаТекста);
    Если Результат <> Неопределено Тогда
        // Артикул найден
    КонецЕсли;
КонецЦикла;

Важный нюанс: при использовании регулярных выражений крайне важно предварительно отсортировать артикулы по длине (от самых длинных к самым коротким), чтобы избежать ложных срабатываний (например, чтобы артикул "A123" не «перехватил» поиск артикула "A12345").

Метод 2: Алгоритм N-грамм (триграммы)

Разберем более продвинутый метод, который часто используется в поисковых движках. Суть заключается в том, чтобы разбить каждый артикул на мелкие части по 3 символа (триграммы). Рассмотрим этапы реализации:

  1. Создаем таблицу соответствия Триграмма -> СписокАртикулов.
  2. Для каждого наименования из файла также выделяем все возможные триграммы.
  3. Ищем в таблице только те артикулы, у которых совпадает хотя бы одна (или несколько) триграмм с наименованием.

Это позволяет мгновенно отсеять 99% артикулов, которые заведомо не могут содержаться в данной строке, и проводить детальную проверку СтрНайти() только для узкого круга кандидатов.

Метод 3: Оптимизация через SQL (подход с временными таблицами)

Проанализируем ситуацию, если данные уже загружены в СУБД. Можно использовать возможности SQL-сервера для быстрого сопоставления. Основная хитрость заключается в индексации. Поскольку стандартный индекс по LIKE '%Артикул%' не работает, мы можем создать таблицу «всех возможных подстрок» для наименований товаров.

Выясним причину эффективности этого метода: если мы разобьем каждое наименование на все возможные варианты (отрезая по одному символу слева), мы получим огромную таблицу, но по ней можно будет искать артикулы с использованием индекса по началу строки. Рассмотрим схему:


// Логика формирования таблицы подстрок
Наименование: "Арт-12345"
Подстроки: 
"Арт-12345"
"рт-12345"
"т-12345"
"-12345"
"12345" // Совпадение!

При использовании INNER JOIN по условию Подстрока LIKE Артикул + '%' SQL-сервер задействует индекс, что даст колоссальный прирост скорости.

Метод 4: Алгоритм Ахо-Корасик (Aho-Corasick)

Это наиболее мощный алгоритм для одновременного поиска множества подстрок. Он строит дерево (бор) из всех ваших 400 000 артикулов. После построения дерева вы один раз проходите по строке наименования, и алгоритм «автоматически» сообщает о всех найденных артикулах.

Преимущество: скорость поиска не зависит от количества артикулов, а зависит только от общей длины текста в файле. Реализовать полноценный автомат Ахо-Корасик на 1С сложно из-за отсутствия низкоуровневой работы с памятью, но можно использовать объект Соответствие для эмуляции узлов дерева.

Метод 5: Предварительная нормализация (Канонизация)

Прежде чем приступать к поиску любым из методов, обязательно выполним нормализацию данных. Зачастую поиск не срабатывает из-за лишних пробелов, дефисов или разного регистра. Рассмотрим шаги подготовки:

  1. Приведем все артикулы и наименования к верхнему регистру.
  2. Создадим «очищенную» копию артикула, удалив все спецсимволы (оставив только буквы и цифры).
  3. При поиске в наименовании также будем использовать «очищенную» подстроку.

Практические советы по реализации в 1С

Посмотрим на рекомендации, которые помогут ускорить процесс даже при использовании простых циклов:

Подводя итог, можно сказать, что для объемов в 400 000 артикулов оптимальным решением будет либо использование внешнего скрипта на Python (библиотека flashtext или re), либо реализация триграммного фильтра внутри 1С для предварительного отсева кандидатов.

← На главную