предисловие
В течение этого времени функция поиска продукта сохраняется, и каждый раз, когда я вижу его в управленческом кабинетеelasticsearch
Мне очень любопытно, как он сделал это с такой эффективной эффективностью запросов.
Это даже больше, чем в моем локальном использованииMySQL
Запросы по первичному ключу также выполняются быстрее.
Для этого я искал соответствующую информацию:
В интернете есть много ответов на такого рода вопросы, что примерно означает следующее:
- ЭС основан на
Lucene
Механизм полнотекстового поиска, который сегментирует данные и сохраняет индекс, хорошо справляется с большим объемом данных индекса по сравнению сMySQL
Он не подходит для частого обновления данных и связанных запросов.
Он не очень тщательный, и в нем нет анализа соответствующих принципов, но, поскольку индекс неоднократно упоминался, давайте сравним различия между ними с точки зрения индекса.
индексы MySQL
начать сMySQL
Кстати говоря, слово индекс должно быть всем знакомо, оно обычно присутствует в некоторых сценариях запросов, что является типичным случаем замены пространства временем.
以下内容以 Innodb 引擎为例。
общие структуры данных
Предположим, мы проектируем его самиMySQL
индекс, какие есть варианты?
хеш-таблица
Первое, о чем мы должны подумать, это хеш-таблица, которая является очень распространенной и эффективной структурой данных для запросов и записи, соответствующейJava
в центреHashMap
Эта структура данных не нуждается в особом представлении, эффективность ее записи очень высока.O(1)
, например, мы хотим запроситьid=3
, вам нужно выполнить хэш-операцию над 3, а затем найти соответствующую позицию в этом массиве.
но если мы хотим запросить1≤id≤6
Для таких интервальных данных хеш-таблица не может быть полностью удовлетворена, поскольку она неупорядочена, необходимо просмотреть все данные, чтобы узнать, какие данные принадлежат этому интервалу.
отсортированный массив
Эффективность запросов упорядоченных массивов также очень высока, когда мы хотим запроситьid=4
Когда данные хранятся, для эффективного поиска данных можно использовать только двоичный поиск.O(logn)
.
В то же время, поскольку данные также упорядочены, они, естественно, могут поддерживать интервальные запросы, поэтому кажется, что упорядоченные массивы подходят для использования в качестве индексов?
Конечно нет, у него есть еще одна серьезная проблема; предположим, мы вставляемid=2.5
данных, все последующие данные должны быть перемещены на один бит одновременно, и эффективность записи станет очень низкой.
Сбалансированное бинарное дерево
Так как эффективность записи упорядоченного массива невелика, давайте посмотрим на высокую эффективность записи, и легко думать о двоичном дереве; здесь мы возьмем в качестве примера сбалансированное двоичное дерево:
Благодаря свойствам сбалансированных бинарных деревьев:
Левый узел меньше родительского узла, а правый узел больше родительского узла.
Итак, допустим, мы хотим запроситьid=11
данные, просто запрос10—>12—>11
Данные могут быть окончательно найдены, а временная сложностьO(logn)
, аналогично при записи данных тожеO(logn)
.
Но он по-прежнему не очень хорошо поддерживает поиск по диапазону интервалов. Предположим, мы хотим запросить5≤id≤20
Когда данные сохраняются, необходимо сначала запросить левое поддерево из 10 узлов, а затем запросить правое поддерево из 10 узлов, и, наконец, можно запросить все данные.
В результате эффективность запросов невысока.
пропустить стол
Таблица пропуска может быть не так распространена, как хеш-таблица, упорядоченный массив и двоичное дерево, упомянутые выше, но на самом делеRedis
серединаsort set
Реализована таблица пропуска.
Здесь мы кратко расскажем о преимуществах структуры данных, реализованной таблицей переходов.
Все мы знаем, что даже дляупорядоченный связанный списокЭффективность запроса невысока, так как он не может использовать индекс массива для бинарного поиска, поэтому временная сложность составляетo(n)
Но мы также можем разумно оптимизировать связанный список, чтобы замаскировать бинарный поиск, как показано ниже:
Мы можем извлечь индекс первого уровня и индекс второго уровня для данных нижнего уровня.В соответствии с разным объемом данных мы можем извлечь индекс N-уровня.
Когда мы запрашиваем, мы можем использовать здесь индекс для скрытой реализации бинарного поиска.
Предположим, теперь вы хотите запроситьid=13
данные, просто пройдитесь1—>7—>10—>13
Только четыре узла могут запрашивать данные, и когда их больше, повышение эффективности будет более очевидным.
В то же время также поддерживается интервальный запрос.Похоже на запрос одного узла только что, вам нужно только запросить начальный узел, а затем пройти его последовательно (связанный список упорядочен) к целевому узлу, чтобы запросить весь диапазон данных.
В то же время, поскольку мы не храним в индексе реальные данные, а храним только указатель, пространство, занимаемое связным списком, в котором хранятся данные внизу, можно не учитывать.
Оптимизация сбалансированного бинарного дерева
Но на самом делеMySQL
серединаInnodb
Вместо использования таблицы пропускаB+
древовидная структура данных.
Эта структура данных не похожа на бинарное дерево, которое преподаватели университетов часто называют базовой структурой данных, потому что этот тип структуры данных развивается из базовой структуры данных в реальной инженерии в соответствии со сценарием спроса.
такой как здесьB+
Можно считать, что дерево произошло от сбалансированного бинарного дерева.
Только что мы упоминали, что эффективность интервального запроса бинарного дерева невысока, и его можно оптимизировать для этого момента:
После оптимизации на основе исходного бинарного дерева: все нелистовые не хранят данные, а служат только индексами листовых узлов, а все данные хранятся в листовых узлах.
Таким образом, данные всех конечных узлов хранятся упорядоченно, что вполне может поддерживать интервальные запросы.
Вам нужно только сначала запросить положение начального узла, а затем по очереди пройти листовые узлы.
Когда объем данных огромен, очевидно, что индексный файл не может храниться в памяти, хотя скорость высокая, потребление ресурсов не мало, поэтомуMySQL
Индексный файл будет храниться непосредственно на диске.
Это немного отличается от упомянутого ниже индекса elasticsearch.
Так как индекс хранится на диске, нам нужно максимально сократить IO с диском (эффективность дискового IO не того порядка, что памяти)
Как видно из приведенного выше рисунка, для запроса фрагмента данных нам необходимо выполнить не менее 4 операций ввода-вывода.Очевидно, что количество операций ввода-вывода тесно связано с высотой дерева.Чем ниже высота дерева, тем меньше IOs и тем лучше производительность.
Так как же уменьшить высоту дерева?
Мы можем попытаться изменить бинарное дерево на троичное дерево, так что высота дерева будет значительно уменьшена, так что количество операций ввода-вывода при запросе данных, естественно, уменьшится, а эффективность запросов также значительно улучшится.
На самом деле это происхождение дерева B+.
Несколько советов по использованию индексов
На самом деле, через приведенный выше рисунокB+树
Он также может оптимизировать некоторые мелкие детали повседневной работы; например, почему это должно быть упорядоченным шагом?
Предполагая, что данные первичного ключа, которые мы записываем, вышли из строя, возможно, что идентификатор данных, записанных позже, меньше, чем идентификатор, записанный ранее, так что обслуживаниеB+树
При индексировании может потребоваться перемещение уже записанных данных.
Если данные записываются инкрементально, такого рассмотрения нет, и необходимо только записывать каждый раз последовательно.
Поэтому мы будем требовать, чтобы первичный ключ базы данных увеличивался как можно больше, и разумнее всего не рассматривать ситуацию с подтаблицами — это самоинкрементный первичный ключ.
В целом идея аналогична таблице пропуска, но внесены соответствующие коррективы под сценарии использования (например, все данные хранятся в листовых узлах).
индекс ЭС
MySQL
Теперь, когда мы закончили разговор, давайте посмотримElasticsearch
Как пользоваться индексом.
положительный индекс
В ES метод называется倒排索引
Структура данных ; давайте поговорим о противоположности ему, прежде чем формально говорить об инвертированном индексе正排索引
.
Возьмите приведенный выше рисунок в качестве примера, мы можем пройтиdoc_id
Способ запроса к конкретному объекту называется с помощью正排索引
, по сути, тоже можно понимать как хеш-таблицу.
Суть в том, чтобы найти значение по ключу.
например, черезdoc_id=4
можно быстро найтиname=jetty wang,age=20
эти данные.
Перевернутый индекс
Затем, если, в свою очередь, я хочу запроситьname
содержитli
Какие данные? Как сделать запрос эффективно?
Только через положительный индекс, упомянутый выше, очевидно, не имеет никакого эффекта.Вы можете только пройти все данные по очереди, чтобы определить, содержит ли имяli
; Это очень неэффективно.
Но если мы перестроим структуру индекса:
когда спрашиваешьname
содержитli
, вам нужно только запросить данные через эту структуру индексаPosting List
Данные, содержащиеся в данных, затем запрашиваются для окончательных данных путем сопоставления.
Эта индексная структура на самом деле倒排索引
.
Term Dictionary
Но как эффективно выполнять запросы в этой структуре индексаli
Ну, в сочетании с нашим предыдущим опытом, пока мы будемTerm
Упорядоченное расположение, вы можете использовать структуру данных дерева поиска двоичного дерева вo(logn)
Запросите данные ниже.
Разбить текст на отдельные частиTerm
На самом деле процесс — это причастие, которое мы часто произносим.
и положить всеTerm
В совокупности это одноTerm Dictionary
, также известный как словарь слов.
- Сегментация слов в английском языке относительно проста. Вам нужно только разделить текст пробелами и знаками препинания, чтобы разделить слова. Китайский язык относительно сложен, но для его поддержки также существует множество инструментов с открытым исходным кодом (поскольку это не является предметом этой статьи, вы можете искать самостоятельно, если вас интересует сегментация слов).
Когда объем нашего текста огромен, после сегментации словTerm
Их тоже будет много.Если хранить в памяти такую инвертированную индексную структуру данных, то ее точно будет мало, но если что-то вродеMySQL
При таком хранении на диске эффективность не так высока.
Term Index
Таким образом, мы можем выбрать компромиссный метод, так как невозможно объединить всеTerm Dictionary
в память, то мы можемTerm Dictionary
Создайте индекс и поместите его в память.
Это позволяет эффективно запрашиватьTerm Dictionary
, и, наконец, пройтиTerm Dictionary
ЗапрошеноPosting List
.
относительноMySQL
серединаB+树
Это также уменьшит в несколько раз磁盘IO
.
этоTerm Index
Мы можем использовать что-то вроде этогоTrie树
Это то, что мы часто говорим字典树
хранить.
Дополнительные сведения о словарных деревьях см.здесь.
если мыj
началоTerm
Для поиска, первый шаг - передатьTerm Index
запрос сj
возглавлялTerm
существуетTerm Dictionary
Где в файле словаря (это место может быть указателем файла, возможно, диапазоном интервалов).
Сразу после размещения всехTerm
Выньте, поскольку он был отсортирован, вы можете быстро найти конкретное место с помощью двоичного поиска; таким образом, вы можете запроситьPosting List
.
наконец прошлоPosting List
Информация о местоположении в исходном файле может быть извлечена из целевых данных.
больше оптимизаций
КонечноElasticSearch
Также было сделано множество целевых оптимизаций.Когда мы извлекаем два поля, мы можем использоватьbitmap
оптимизировать.
Например, теперь вам нужно запроситьname=li and age=18
Данные, то нам нужно передать эти два поля в соответствующие результатыPosting List
выиграть.
Самый простой способ — обойти две коллекции по отдельности и удалить повторяющиеся данные, но это явно неэффективно.
Тогда мы можем использоватьbitmap
способ хранения (и экономии места для хранения), используя при этом врожденные位与
Рассчитать результат.
[1, 3, 5]
⇒10101
[1, 2, 4, 5]
⇒11011
Результат суммирования двух двоичных массивов таким образом:
10001
⇒[1, 5]
окончательное решениеPosting List
за[1, 5]
, этот КПД, естественно, гораздо выше.
Тот же запрос нуждается вMySQL
Особой оптимизации в нем нет, но сначала фильтруются данные с малым объемом данных, а потом фильтруется второе поле, и эффективность естественно не высокая.ES
высокий.
Конечно в последней версииES
тоже правильноPosting List
Сжатие, конкретные правила сжатия можно просмотретьофициальная документация, который здесь подробно не описан.
Суммировать
Наконец, подведем итоги:
Из приведенного выше контента видно, что какими бы сложными в конечном счете продукты ни были составлены из базовых структур данных, они будут оптимизированы только для разных сценариев применения.Чтобы быстро приступить к работе, вы можете даже сами знать направление оптимизации.
Наконец нарисуйте пирог, я постараюсь следоватьES
Идея инвертированного индексирования — это автономная поисковая система, и вы можете углубить свое понимание, только написав ее самостоятельно.
Чтобы получить больше удовольствия от чтения, посетитездесь:woohoo.notion.so/эластичное шептало…
Ваши лайки и репост - лучшая поддержка для меня