1с ускорение полнотекстового поиска

Tarantool: история ускорения поиска в 1С

Недавно у наших добрых друзей из крупной розничной сети возникла задача ускорения поиска в 1С.

Во-первых, искать нужно было по клиентам (три справочника, 9 текстовых полей, поиск типа %like%) и всего-то по 2,5 млн записей. Сразу скажем, что полнотекстовый поиск и морфология — это пока не про Tarantool. В результате ряда экспериментов мы остановились на ElasticSearch, но т.к. он не в тему статьи, то можем написать отдельную, если будет интерес. Скажем только, что скорость выросла на порядок по сравнению с тем, что мы могли выжать из полнотекстового поиска MS SQL.

Во-вторых, нужен был поиск и подбор по товарам с выводом остатков по всем складам без дополнительных запросов. Скорость поиска должна была быть сопоставима с обычным откликом интерфейса, то есть около 0,2 сек вместо текущих 5-12 секунд в 1С (в зависимости от уровня нагрузки). 90 тысяч строк, список номенклатур меняется не часто, примерно по 10-50 позиций в день.

Stage 1

И тут в полный рост встал вопрос онлайн-обновления остатков товаров на складах. В двух 1С (производственная и розничная) в общей сложности было порядка 700 складов с постоянно меняющимися остатками и 90 тысяч активных позиций товаров. Планируемая система должна была переваривать 200 пользовательских запросов по остаткам в секунду.

Первым делом посмотрели, что нам скажет Elastic. И мгновенно уперлись в проблему реиндексации (остатки меняются часто и помногу) и значительного замедления поиска из-за вложенности складов и остатков. При 50 запросах в секунду на поиск и при одновременном изменении порядка 100 записей в секунду реиндексация начинала отставать, и скорость поиска росла экспоненциально.

Далее были MySQL и PostgreSQL, результат был примерно одинаковый. Один запрос к номенклатуре от пользователя рассыпался в среднем на 10 запросов к характеристикам номенклатуры и поиску остатков 10 характеристик по 700 складам. При 10 пользовательских запросах в секунду и тех же 100 рандомных insert в секунду поиск был около 0,9 сек, а при 20 запросах уходил за 2,5 секунды. При 30 одновременных запросах всё было сравнимо с поиском в 1С.

Наши 1С-эксперты заявили, что «сейчас оптимизируют поиск в 1С и никаких сторонних систем нам не надо». Пропущу результат и сразу перейду к той части, где 1С-эксперты сказали, что «ну, тогда мы будем обращаться напрямую к MS SQL».

MS SQL показал себя лучше и выдохся примерно на 45 запросах. После чего мы согласились, что нам нужна in-memory БД.

Дальше был скучный поиск решения, которое работало бы с требуемой производительностью и при этом восстанавливалось при перезапуске серверов не позднее, чем через 3-5 секунд.

Мы понимали, что нужны будут очереди, регулярный сброс данных на диск, система восстановления текущих остатков по товарам в случае аварийного перерыва в работе серверов (без потери данных из памяти) и шардирование (оно было бы нужно при любом выбранном варианте, но не хотелось сильно костылить).

Также мы понимали, что вместо привычной в эксплуатации системы на 1С мы получим затратный по администрированию и контролю показателей набор систем.

Конечно, мы начали экспериментировать со стеком RabbitMQ + Memcached / Redis, но открытым оставался вопрос сохранения данных в случае сбоя и быстрой их подгрузки. К тому же нужно было придумывать механизм подтверждения обмена данными с 1С. В довершении всего этот стек не решал будущую задачу — построение «центрального хранилища данных» с быстрым поиском.

Параллельно с этим мы изучали возможности MS SQL 2017 — Memory Optimized Tables.

И вот тут мы познакомились с Tarantool.

Отсутствие хорошей документации и понимания логики разработчиков этого «комбайна» поначалу выбили нас из колеи. Но проведенные замеры показали превосходную скорость поисковой выдачи, а заверения производителя о масштабном шардировании, сохранности данных в случае сбоя, восстановлении (прогревании) данных в течение нескольких секунд после старта сервисов и встроенном механизме очередей заставили нас вплотную погрузиться в изучение.

К сожалению, первичных результатов замеров не сохранилось, поэтому прикладываю более поздние результаты, только для сравнения MS SQL с Tarantool.

Читайте также:  Генератор аврора объем масла

Выполняли префиксный поиск (текст*) без морфологии и учета ошибок по базе примерно в 5 млн пользователей (15 полей для каждого пользователя, включая связанные данные, например, бонусные карты).

Stage 2

Первое, что мы сделали после экспериментальных замеров, это поставили Tarantool 2.1 с поддержкой SQL-команд и коннектор к Tarantool на PHP.

Какое-то время ушло на осознание, что каждый инстанс Tarantool является однопоточным и нужно поднимать много инстансов для распределенных запросов, а не выжимать всё из одного.
Далее мы разбирались с компоновкой данных и тем, как их правильно разложить. В итоге написали на Lua свой велосипед по шардированию (тогда мы ещё не знали о Tarantool Cartridge и Vshard). Результаты показали длительность поиска от 0,004 сек до 0,21 сек в зависимости от нагрузки. Последнее значение получено при 30 пользовательских запросах к одному инстансу и 100 обновлениях данных в секунду. Встроенным шардированием до 7 инстансов мы получили требуемые показатели производительности.

По мере знакомства с Tarantool мы всё больше понимали, что использование SQL — это просто привычка. Мы попробовали реализовать всё то же самое на Lua, и результат превзошёл все ожидания. Загрузка и обработка массива данных из 6 млн. записей в первоначальной SQL-реализации занимала до 20 минут, а после перехода на Lua этот же массив стал обрабатываться за 50 секунд и, как бонус, мы получили уменьшение нагрузки на 1С за счет прироста скорости выгрузки.

С помощью двух инстансов Tarantool (мастер и read only, по updated: 3 ядра и 1,5 Гб памяти на инстанс) мы добились требуемой производительности: MS SQL не смог показать хорошую скорость при 50 запросах в секунду, а на Tarantool мы смогли выжать 120 запросов в секунду на одном инстансе (и это не предел: мы тестировали на Tarantool версии 2.2, но разработчики говорят, что в версии 2.3 выборка по префиксу стала использовать индекс, поэтому на Tarantool 2.3 результаты должны быть еще лучше — мы проверим это и добавим результаты в статью). В обоих случаях мы упирались в загрузку процессора. В среднем за 1 запрос выгружалось до 300 строк, данные при этом все хранились в памяти (Tarantool memtx).

Текущий код написан на Lua, встроенном в Tarantool. Порог вхождения в язык для нас оказался минимальный.

Вот пример одной из функций: добавление товаров в очередь обмена с ElasticSearch.

Теперь мы ищем в ElasticSearch с учетом морфологии и ошибок по наименованиям/свойствам и другим текстовым полям, а после этого запрашиваем данные о наличии товаров в различных разрезах в Tarantool и возвращаем результат.

Примерная схема работы такая:

Система получилась простая, легко администрируемая, с контролем показателей и быстрым запуском в случае сбоя. В неё легко, прямо на лету, можно добавлять новые инстансы или отключать их.

Мы мониторим показатели ресурса сервера (процессор, память, диски) и показатели Tarantool box.slab.info. Со стороны 1С мониторится уменьшение очереди на отправку и отсутствие ошибок в ответе от бэкенда. В случае достижения пороговых значений оповещается техподдержка.

И да, мы очень благодарны специалистам Mail.ru Group, которые отвечали на наши вопросы, и сообществу в Telegram, которое пока небольшое, но очень активное.

Stage 3

«Ну вот, — подумали мы. — Всё так здорово работает. А не подключить ли нам сайт напрямую к Tarantool, чтобы избавиться от медленных Bitrix-обменов и Bitrix-кеширования?» (кто в теме, тот грустит вместе с нами)

«Почему только сайт? — спросил заказчик. — Наверняка туда нужно подключить мобильное приложение, партнеров и франшизу».

«Ух» — сказали мы, и поскольку представление о быстром хранилище данных уже сложилось, мы ушли придумывать шину обмена данных на Tarantool. Надо сказать, что результаты уже впечатляющие. Напишем, если эта тема вам, уважаемые читатели, зайдет.

Источник

Ускоряем полнотекстовый поиск в динамических списках

Предисловие

Прочитал статью коллеги Полнотекстовый поиск в 1С. №1 Грабли в динамических списках в которой автор описывает типовую ситуацию всех баз с большим количеством документов. При этом был разобран случай без использования РЛС, если у автора поиск длится 8 сек, то у обычного пользователя с ограничением на уровне записей он будет длиться около 20 сек (даже если фактического ограничения нет, а рлс включен).

Я честно старался, писал в 1С письма (последние, наверное, 4 года). Под разными предлогами признать и исправить очевидные проблемы полнотекстового поиска

  • медленно, все как и описано в статье
  • и не всегда ищет

Я, например, считаю что поиск должен данные найти и неважно какая технология используется, это sql запрос или свой полнотекстовый поиск.

Поддержка сказала, цитата

«Алгоритм поиска ППД такой, что поиск производится только с начала строки» — это для Вас пояснение алгоритма работы полнотекстового поиска, что по середине строки он не найдет

Результат на такие обращения — ссылки на ИТС, изучайте документацию, с системой все норм.

Но решение, подходящее для меня нашел и решил внести вклад в развитие сообщества, может это избавит кого-то от головной боли.

Применяя метод костылей

Суть «метода» заключается в том чтобы заблокировать отбор по некоторым, ненужным нам полям динамического списка. Этот метод не блокирует возможности установки отборов через настройку списка или «быстрых отборов» отдельно выведенных на форму создателями типовых конфигураций. Единственный минус, который я заметил, если заблокированное поле является частью условия для условного оформления — оформление ломается. Ниже приведен код, который ограничит все поля динамического списка, кроме тех, которые есть в условном оформлении и нужны нам для поиска.

Эту процедуру можно разместить в «своем» общем модуле. У меня УТ 11.4 — поэтому примеры соответствуют этой конфигурации.

Пример вызова процедуры для списка заказов клиента из модуля формы:

Эффект — потрясающий. Для полноправного пользователя поиск длится около 1 сек (для базы с миллионом и более документов). Для пользователя с РЛС поиск длятся около 2 сек. Без дополнительных отборов по организации, менеджеру, дате.

Пример для формы подбора товаров:

Форма подбор товаров в документ продажи, мне для поиска нужны только артикул и наименование:

Подбор, благодаря «правкам» был довольно шустрый (1-2 сек для пользователя), но с ограничением по полям результаты появляются еще до ввода строки (шутка), моментально.

Писака не писатель, это мой первый раз и т.д. прошу меня простить за допущенные ошибки.

Источник

1С 8.3 : Полнотекстовый поиск в 1С (что это и пример использования)

Полнотекстовый поиск — позволит найти текстовую информацию, размещенную практически в любом месте используемой конфигурации. При этом искать нужные данные можно либо по всей конфигурации в целом, либо сузив область поиска до нескольких объектов (например, определенных видов документов или справочников). Сами критерии поиска могут варьироваться в довольно широком диапазоне. То есть найти нужные данные можно, даже не помня точно, где они хранятся в конфигурации и как именно записаны.

Полнотекстовый поиск предоставляет следующие возможности:

  • Есть поддержка транслитерации (написание русских слов символами латиницы в соответствии с ГОСТ 7.79-2000). Пример: «русская фраза» = «russkaya fraza».
  • Есть поддержка замещения (написание части символов в русских словах одноклавишными латинскими символами). Пример: «руссrfz фраpf» (окончания каждого слова набраны латиницей, допустим, в результате ошибки оператора).
  • Есть возможность нечеткого поиска (буквы в найденных словах могут отличаться) с указанием порога нечеткости. Пример: указав в строке поиска слово «привет» и нечеткость 17 %, найдем все аналогичные слова с ошибками и без: «привет», «превет», «привед».
  • Есть возможность указать область выполнения поиска по выбранным объектам метаданных.
  • Полнотекстовое индексирование названий стандартных полей («Код», «Наименование» и т. д.) производится на всех языках конфигурации.
  • Поиск выполняется с учетом синонимов русского, английского и украинского языков.
  • Морфологический словарь русского языка содержит ряд специфических слов, относящихся к областям деятельности, автоматизируемым с помощью системы программ «1С:Предприятие».
  • Стандартно в состав поставляемых словарей включены словарные базы и словари тезауруса и синонимов русского, украинского и английского языков, которые предоставлены компанией «Информатик».
  • Поиск можно осуществлять с использованием подстановочных символов («*»), а также с указанием поисковых операторов («И», «ИЛИ», «НЕ», «РЯДОМ») и спецсимволов.

Полнотекстовый поиск можно осуществлять в любой конфигурации на платформе 1С:Предприятие 8

Для того чтобы открыть окно управления полнотекстовым поиском необходимо выполнить следующее:

Обычное приложение — пункт меню Операции — Управление полнотекстовым поиском.

Управляемое приложение — пункт меню Главное меню — Все функции — Стандартные — Управление полнотекстовым поиском.

  • Обновить индекс – Создание индекса/Обновление индекса;
  • Очистить индекс – обнуление индекса(рекомендуется после обновления всех данных);
  • пункт Разрешить слияние индексов – отвечает за слияние основного и дополнительного индекса.

Полнотекстовый поиск осуществляется при помощи полнотекстового индекса. При отсутствии индекса полнотекстовый поиск как таковой не возможен. Для того чтобы поиск имел результат, все необходимые данные должны быть включены в полнотекстовый индекс. Если пользователем введены в базу новые данные, их следует включить в рассматриваемый индекс, иначе они не будут участвовать в поиске. Чтобы этого избежать, необходимо обновлять полнотекстовый индекс. При обновлении система анализирует только определенные типы данных: Строка, Данные ссылочного типа (ссылки на документы, справочники),Число, Дата, ХранилищеЗначения. Если пользователь не имеет прав доступа к определенной информации, то он не сможет увидеть ее в результатах поиска. Следует также помнить и о том, что в свойствах объектов, по которым будет происходить поиск должно быть установлено значение Полнотекстовый Поиск – Использовать, которое задано по умолчанию.

Как вы можете заметить свойство Использовать установлено для всего справочника Контрагенты, но сделать это можно и для каждого его реквизита соответствующего типа.

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

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

Механизм полнотекстового поиска допускает написание части символов русского слова одноклавишными латинскими символами. Результат поиска при этом не измениться.

Два оператора РЯДОМ

  • упрощенный. На расстоянии 8 слов друг от друга
  • РЯДОМ/[+/-]n – поиск данных в одном реквизите на расстоянии n-1 слов между ними.

Знак указывает в каком направлении от первого слова будет поиск второго. (+ — после, — до)

Групповой символ «*» может использоваться только в качестве замены конца слова

Оператор нечеткости «#». Если неизвестно точное написание названия, имени.

Программными средствами и средствами 1с: программирование.

Оператор синонимов «!». Позволяет найти слово и его синонимы

Как программно обновить индекс полнотекстового поиска?

Пример полнотекстового поиска данных

Определение переменной СписокПоиска

Кроме этого в процедуре обработки события ПриОткрыии формы определим, что эта переменная будет содержать список полнотекстового поиска, с помощью которого мы и будем осуществлять поиск в данных

Теперь для события нажатия на кнопку Найти напишем код, который позволит нам выполнять поиск в соответствии с тем выражением, которое задано в поле ПоисковоеВыражение

Сначала в этой процедуре мы устанавливаем поисковое выражение, введенное пользователем, в качестве строки поиска для полнотекстового поиска. Затем выполняем метод ПерваяЧасть(), который собственно запускает полнотекстовый поиск и возвращает первую порцию результатов. По умолчанию порция содержит 20 элементов. После этого мы анализируем количество элементов в списке поиска. Если он не содержит ни одного элемента, то мы выводим в форму соответствующее сообщение. В противном случае вызывается процедура ВывестиРезультатПоиска(), которая отображает полученные результаты пользователю.

Создадим в модуле формы процедуру с таким именем и напишем в ней код,

Действия, выполняемые в этой процедуре, просты. Сначала мы формируем сообщение о том, какие элементы отображены и сколько всего элементов найдено. Затем получаем результат полнотекстового поиска в виде HTML-текста и выводим этот текст в поле HTML-документа, расположенное в форме.

В заключение передаем управление в процедуру ДоступностьКнопок() для того, чтобы сделать доступными или, наоборот, запретить доступ к кнопкам Предыдущая порция и Следующая порция (в зависимости от того, какая порция полученных результатов отображена). Текст этой процедуры представлен в Коде

Теперь необходимо создать обработчики событий нажатия на кнопки ПредыдущаяПорция() и СледующаяПорция().

Заключительным «штрихом» будет создание обработчика события onclick поля HTML-документа, расположенного в форме. Дело в том, что результат полнотекстового поиска, представленный в виде HTML-текста, содержит гиперссылки на номера элементов списка поиска. И нам хотелось бы, чтобы при переходе пользователя на эту ссылку система открывала бы форму того объекта, который содержится в этом элементе списка. Для этого мы будем перехватывать событие onclick HTML-документа, содержащегося в поле HTML-документа, получать номер элемента списка из гиперссылки и открывать форму соответствующего объекта. Текст обработчика события onclick поля HTML-документа представлен в коде

Источник

Читайте также:  Как измерить объем ковша погрузчика
Поделиться с друзьями
Объясняем