MySQL索引 VS ElasticSearch索引


当前第2页 返回上一页

那怎样才能降低树的高度呢?

我们可以尝试把二叉树变为三叉树,这样树的高度就会下降很多,这样查询数据时的 IO 次数自然也会降低,同时查询效率也会提高许多。

这其实就是 B+ 树的由来。

使用索引的一些建议

其实通过上图对 B+树的理解,也能优化日常工作的一些小细节;比如为什么需要最好是有序递增的?

假设我们写入的主键数据是无序的,那么有可能后写入数据的 id 小于之前写入的,这样在维护 B+树 索引时便有可能需要移动已经写好数据。

如果是按照递增写入数据时则不会有这个考虑,每次只需要依次写入即可。

所以我们才会要求数据库主键尽量是趋势递增的,不考虑分表的情况时最合理的就是自增主键。

整体来看思路和跳表类似,只是针对使用场景做了相关的调整(比如数据全部存储于叶子节点)。

ES 索引

MySQL 聊完了,现在来看看 Elasticsearch 是如何来使用索引的。

正排索引

在 ES 中采用的是一种名叫倒排索引的数据结构;在正式讲倒排索引之前先来聊聊和他相反的正排索引

以上图为例,我们可以通过 doc_id 查询到具体对象的方式称为使用正排索引,其实也能理解为一种散列表。

本质是通过 key 来查找 value。

比如通过 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 打头的 TermTerm 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 倒排索引的思路做一个单机版的搜索引擎,只有自己写一遍才能加深理解。

相关免费学习推荐:mysql数据库(视频)

以上就是MySQL索引 VS ElasticSearch索引的详细内容,更多文章请关注木庄网络博客

返回前面的内容

相关阅读 >>

哭..我以为我很懂MySQL索引

MySQL索引是什么及怎么使用的?整理的很详细

mysql需要在哪些字段上加索引?

MySQL索引的原理

mysql怎么添加索引

MySQL索引是什么?MySQL索引的相关知识介绍

什么是MySQL索引?【详解】

详解MySQL索引的底层实现原理

MySQL索引有哪些?

mysql的索引底层之实现原理

更多相关阅读请进入《MySQL索引》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...