Разработка поисковой системы

Автор: Тихонов Александр Николаевич, Стучилин Владимир Валерьевич

Журнал: Горные науки и технологии @gornye-nauki-tekhnologii

Статья в выпуске: 11, 2012 года.

Бесплатный доступ

В статье описывается процесс разработки поисковой системы для web- сайта.

Поисковая система, полнотекстовый поиск, база данных, поисковый паук, web-интерфейс

Короткий адрес: https://sciup.org/140215436

IDR: 140215436

Текст научной статьи Разработка поисковой системы

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

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

Определение задачи

Согласно ГОСТ 7.73-96 СИБИД "Поиск и распространение информации. Термины и определения":  полнотекстовый поиск:

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

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

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

Существующие решения

В настоящее время существует несколько вариантов реализации системы полнотекстового поиска. Рассмотрим наиболее распространенные из них:

Lucene

The Apache Lucene — это свободная библиотека для высокоскоростного полнотекстового поиска, написанная на Java. Может быть использована для поиска в интернете и других областях компьютерной лингвистики (аналитическая философия).

Sphinx

Sphinx (англ. SQL Phrase Index) — система полнотекстового поиска, распространяемая по лицензии GNU GPL. Отличительной особенностью является высокая скорость индексации и поиска, а так же интеграция с существующими СУБД и API для распространённых языков веб-програмирования.

DataparkSearch Engine

DataparkSearch Engine — поисковая машина с открытым исходным текстом, написанная на языке С. Распространяется по лицензии GNU GPL. Предназначена для организации поиска на одном или многих веб-серверах.

PostgreSQL tsearch2

PostgreSQL — свободная объектно-реляционная система управления базами данных (СУБД)[2]. Сильными сторонами PostgreSQL считаются:

А поддержка БД практически неограниченного размера;

^ мощные и надёжные механизмы транзакций и репликации;

^ расширяемая система встроенных языков программирования;

^ наследование;

^ легкая расширяемость.

tsearch2 — расширение PostgreSQL для реализации полнотекстового поиска. Ранее был выполнен в виде отдельного модуля, начиная с версии 8.3 был интегрирован в ядро СУБД.

Выбор

После обзора существующих технологий был выбран вариант на tsearch2. Этому послужили следующие причины:

^ Поиск полностью интегрирован с СУБД. Несмотря на то, что подобные ограничения могут влиять на производительность поиска, полный доступ ко всем метаданным базы данных дает возможность для реализации очень сложных поисков, просто невозможных для внешних поисковиков;

^ Более гибкая настройка индексирования и поиска;

А Существующий опыт и инструменты работы с PostgreSQL;

А Возможность написания расширенных функций на PL/Perl;

А Возможность использования произвольных словарей;

А Сайт уже использует PostgreSQL в качестве основной базы данных.

Поиск в PostgreSQL

Как и многие современные СУБД, PostgreSQL имеет встроенный механизм полнотекстового поиска[2]. Отметим, что операторы поиска по текстовым данных существовали очень давно, это операторы LIKE, ILIKE, ~, ~*. Однако, они не годились для эффективного полнотекстового поиска, так как:

А у них не было лингвистической поддержки;

А они не предоставляют никакой информации для ранжирования документов, что делает такой поиск практически бесполезным;

А они очень медленные из-за того, что они каждый раз просматривают весь документ и не имеют индексной поддержки.

Полнотекстовый поиск

Для улучшения ситуации два русских разработчика, Олег Бартунов и Федор Сигаев, предложили и реализовали новый полнотекстовый поиск[3], существовавший как модуль расширения и интегрированный в PostgreSQL, начиная с версии 8.3.

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

PostgreSQL предоставляет возможность как для создания новых типов данных, операторов, так и создания индексной поддержки для доступа к ним, причем с поддержкой конкурентности и восстановления после сбоев. Однако, надо понимать, что индексы нужны только ускорения поиска, сам поиск обязан работать и без них.

Таким образом, были созданы новые типы данных - tsvector, который является хранилищем для лексем из документа, оптимизированного для поиска, и tsquery - для запроса с поддержкой логических операций, полнотекстовый оператор "две собаки" @@ и индексная поддержка для него с использованием GIST и GIN. tsvector помимо самих лексем может хранить информацию о положении лексемы в документе и ее весе

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

Для эффективной работы с такими многомерными данными PostgreSQL предлагает два типа индекса: GIST (Generalized Search Tree) и GIN (Generalized Inverted Index).

GIN индекс, или обобщенный обратный индекс - это структура данных, у которой ключом является лексема, а значением - сортированный список идентификаторов документов, которые содержат эту лексему. Так как в обратном индексе используется бинарное дерево для поиска ключей, то он слабо зависит от их количества и потому хорошо шкалируется. Этот индекс используется практически всеми большими поисковыми машинами, однако его использование в базах данных для индексирования изменяющихся документов затруднено, так как любые изменения приводят к большому количеству обновлений индекса. Этот индекс лучше всего подходит для неменяющихся коллекций документов.

В тоже время, GIST индекс является "прямым" индексом, т.е. для каждого документа ставится в соответствие битовая сигнатура, в которой содержится информация о всех лексемах, которые содержаться в этом документе, поэтому добавление нового документа приводит к добавлению только одной сигнатуры.

GIST был предложен как обобщение нескольких классов индексов (такие как B-Tree, R-Tree, Similarity Tree, RD-Tree) и позволяет создавать индексы на базе произвольной метрики типа данных. Для использования GIST разработчик должен создать метрику и функции-адаптеры, используя API. Как классический индекс, в котором храниться одна и только одна пара ключ-ссылка, индексы GIST имеют хорошею производительность при вставке нового ключа, но производительность при поиске может сильно зависеть от метрики проиндексированного типа данных и собственно типа поискового запроса[5].

По результатам сравнения производительности индексов было выяснено что время поиска в таблице с индексом GIN снизилось почти в 44 раза по сравнению с поиском без использования индексов и в 5,5 раз по сравнению с индексом GIST.

Сравнение индексов

Для определения области применения каждого из индексов необходимо знать их основные различия[4]:

  • А создание индекса - GIN требует в 3 раза больше времени чем GIST;

  • А размер индекса - GIN-индекс в 2-3 раза больше GIST-индекса;

  • Л время поиска - GIN-индекс в 3 раза быстрее, чем GIST-индекс;

  • Л обновление индекса - GIN-индекс обновляется в 10 раз медленнее.

Индексация страниц

Теперь рассмотрим способ внесения документов в базу данных. Для этого необходим http-паук, рекурсивно обходящий страницы сайта. Для того, чтобы ограничить число индексируемых страниц, паук должен учитывать правила для всех индексирующих роботов в соответствии с файлом robots.txt. После получения каждой страницы робот должен извлекать из нее текст без html тегов и вносить его в базу данных.

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

Реализация паука

В соответсвии с перечисленными требованиями был реализован синхронный http-паук с помощью языка perl. Для загрузки документов используется модуль LWP::RobotUA, полностью поддерживающий обработку файла robots.txt и совместимый со стандартным способом загрузки. Для разбора документов html используется парсер XML::Twig. Для повышения эффективности заполнения базы данных все запросы заключены в одну транзакцию, колонка поискового вектора заполняется после записи всех данных и индекс строится в групповом режиме.

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

Web-интерфейс поиска

Для предоставления пользователям возможности производить поиск на сайте необходимо реализовать web-интерфейс с формой поиска и таблицей результатов. В качестве образца были выбраны популярные поисковые сервисы. Таким образом необходима сортировка выдачи по релевантности документов, вывод гиперссылок на документ и части текста документа с подсветкой искомых слов.

В результате был создан интерфейс к поиску. В соответствии с используемыми на сайте технологиями страница поиска выполнена в виде подгружаемой функции для сервера на perl, соединенного с frontend сервером по протоколу fastcgi. Преимущества этого подхода:

В качестве frontend используется web-сервер nginx(один из самый эффективных в высоконагруженных проектах). Он используется для отдачи статических файлов и связи с backend сервером, используемым для генерации динамического контента. Также он используется для кеширования ответов backend сервера.

В отличии от протокола cgi, fastcgi позволяет использовать постоянно запущенный процесс, а не запускать его при каждом запросе. Это значительно повышает производительность и снижает время ответа.

В качестве backend может быть запущено несколько копий сервера на одном порту, либо можно указать несколько портов. Также backend и frontend могут находиться на разных физических серверах. Это позволяет гибко масштабировать архитектуру системы.

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

Для реализации подсветки искомых слов в найденных документах в модуль tsearch2 уже включена функция ts_headline, таким образом задача выделения слов ложится также на базу данных.

Тестирование производительности

Для комфортного взаимодействия пользователя с поисковой системой необходимо чтобы она имела минимальное время отклика. Выявим скорость генерации ответа разработанной системы.

Внутренние механизмы замера времени генерации страницы представлены в табл. 1:

Таблица 1.

Номер запроса

Форма поиска

Выдача результатов

Безрезультатный запроc

Первый запрос

1,411 мс

24,886 мс

6,786 мс

Следующие запросы

0,383 мс

18,443 мс

1,506 мс

Запросы из кеша

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

По результатам теста максимальное время отклика не превышает 30 мс. Это время практически не заметно для пользователя и не препятствует комфортному взаимодействию.

Вывод

В ходе работы были рассмотрены варианты, выбран оптимальный и была разработана система полнотекстового поиска, обладающая высокой скоростью поиска и большой гибкостью индексирования.

Список литературы Разработка поисковой системы

  • Тестирование и отладка полнотекстовой конфигурации. -[Электронный источник] -режим доступа: http://www.sai.msu.su/~megera/postgres/fts/doc/fts-debug.html
  • Бартунов О. Что такое PostgreSQL. -[Электронный источник] -режим доступа: http://www.sai.msu.su/~megera/postgres/talks/what_is_postgresql.html
  • O. Bartunov, T. Sigaev Full-Text Search in PostgreSQL. -[Электронный источник] -режим доступа: http://www.sai.msu.su/~megera/postgres/fts/doc/
  • Gin for PostgreSQL. -[Электронный источник] -режим доступа: http://www.sai.msu.su/~megera/wiki/Gin
  • GIN Presentation on PostgreSQL Anniversary Summit, 2006. -[Электронный источник] -режим доступа: http://www.sigaev.ru/gin/Gin.pdf
Статья научная