Понимание прямого индекса и инвертированного индекса

поисковый движок

предисловие

В последнее время я изучаю и исследую ElasticSearch. ES — популярный поисковый сервер с открытым исходным кодом, который может предоставлять функцию полнотекстового поиска данных в режиме, близком к реальному времени. Одна из наиболее важных идей для реализации функции поиска — использовать倒排索引в чем разница между ним и прямым индексом нашей реляционной базы данных, такой как Mysql? В этой статье я подытожу свое понимание двух видов индексов.

текст

положительный индекс

Взяв в качестве примера кластеризованный индекс Mysql Innodb, как показано на рисунке ниже, структура индекса дерева B+ в минималистской версии (без атрибутов страницы) примерно такая: конечные узлы хранят полные данные, а неконечные узлы хранят соответствующий кластеризованный индекс Поле (первичный ключ), Sql, который может использовать кластеризованный индекс, будет искать дерево B+ сверху вниз по очереди, пока поля не будут согласованы;

CREATE TABLE user_info (
	id int,
	name varchar(16),
	hobby varchar(256)
);

在这里插入图片描述

Для некластеризованного индекса только содержимое конечного узла хранит информацию о первичном ключе таблицы.Порядок запроса состоит в том, чтобы сначала найти согласованные одиночные или несколько идентификаторов первичного ключа в конечном узле через поля некластеризованного index, а затем используйте эти первичные ключи. id для回表и, наконец, получить соответствующие полные данные сущности. Если мы посмотрим на поле хобби хобби в приведенной выше таблице mysql, если у нас есть бизнес-требования: запросите соответствующий список пользователей в соответствии с ключевыми словами хобби пользователя, такими как «баскетбол», как мы можем это сделать, мы можем написать только строку, подобную sql , все Логика сканирования таблицы.

SELECT *
FROM user_info
WHERE hobby LIKE '%篮球%';

    Даже если мы создадим обычный индекс для поля хобби, под движком Innodb, если вы хотите использовать индекс строкового типа в запросе, вы можете только перейти最左前缀Логика индекса, т.е. LIKE 'basketball%'. К счастью, Innodb поддерживает его после версии 5.6.全文索引full text, После создания полнотекстового индекса полнотекстовый индекс можно использовать в запросе с использованием ПОИСКПОЗ и ПРОТИВ, что намного эффективнее, чем полное сканирование таблицы B+ дерева, но соответствующий полнотекстовый индекс будет занимать значительный объем диска космос. Полнотекстовый индекс — это то же самое, что инвертированный индекс, который мы хотим сказать.

SELECT *
FROM user_info
WHERE MATCH (hobby) AGAINST ('篮球');

Перевернутый индекс

По сравнению с прямым индексом дерева B+, если мы индексируем поле хобби, минимальный формат данных его инвертированного индекса выглядит следующим образом. Создадим поле с инвертированным индексом, которое будет проходить через分词器По семантике поля в поле разбиваются на соответствующие терминоиндексы, которые составляют весь терминологический словарь данного типа данных, например, «как баскетбол и пение» будет делиться на «баскетбол» и «пение». индексы терминов; второй столбец содержит идентификатор документа (documentId), соответствующий этим индексам терминов, эти данные могут помочь нам проследить до полных данных объекта; третий столбец — это позиция соответствующего индекса термина в поле документа, 0 Указывает положение в начале, что может помочь отметить выделенную информацию извлеченных данных.

倒排索引.jpg

Инвертированный индекс и сегментация слов

Как создать соответствующий инвертированный индекс после ввода данных документа, таких как {"id":1,"name":"Zhang San","hobby":"Я люблю баскетбол и пение"}. Возьмите ES в качестве примера, вы можете установить поле в строку и соответствующий分词器, будет предварительно обработан для поля хобби. После следующих трех шагов сегментации слов целое предложение будет разделено на несколько соответствующих индексов терминов, а также будут сгенерированы позиция и идентификатор документа, соответствующие каждому индексу термина. структура данных.

  1. Фильтры символов: обработка исходного текста, например удаление тегов html.
  2. Токенизатор: разделите исходный текст на слова по определенным правилам
  3. Фильтры токенов: повторная обработка слов, обработанных Tokenizer, таких как строчные буквы, удаление или добавление и т. д.

Для разного текстового контента мы можем использовать разные токенизаторы или даже пользовательские токенизаторы, такие как токенизаторы ES: Стандартный анализатор (токенизатор по умолчанию, сегментация по словам, обработка пунктуации), Простой анализатор (символы, не являющиеся буквами и буквами). разрезать на точки сегментации), Whitespace Analyzer (токенизатор на основе пространства), IKAnalyzer (более популярный китайский токенизатор); Полнотекстовый индекс Mysql также имеет соответствующий китайский токенизатор ngram.

Порядок запроса двух индексов

Через приведенное выше описание мы можем знать приближенный заказ запроса при использовании передового индекса и инвертированного индекса

正排索引倒排索引查询顺序.jpg

Инвертирующий индекс идеологии

Я уже получил описание требования: нам нужно установить разные правила отображения контента для пользователей из разных городов, классов, семестров и устройств. Эти атрибуты могут быть установлены пустыми. Наконец, если атрибут пользователя соответствует нескольким правилам, то он должен основываться на весе этих атрибутов打分, возьмем правило с наивысшим баллом.Например, мы настраиваем правила следующим образом: Затем приходит пользователь весной первого класса начальной школы Шанхая и сопоставляет два правила, а затем вычисляет значение веса в соответствии с атрибутами два правила и, наконец, выбирает отображение A или B.

city grade term device rule
Шанхай весна показать А
Шанхай Первый класс показать Б

При запросе данных выше sql выглядит следующим образом Идея процесса or аналогична "сегментация слова в инвертированном индексе + поиск всех данных документа, содержащих слово index" (только индекс слова уже определен) , а затем После поиска нескольких записей вычислите значение веса (аналогично оценке релевантности поиска в ES).

SELECT *
FROM tb_rules
WHERE (city = '上海' OR grade = '小学一年级' OR term = '春季')

Суммировать

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