Mysql与ElasticSearch的区别

前几天被问到一个问题,说如果项目使用的是Mysql数据库,并且数据库的访问压力过大怎么办,我回答的是,第一步增加缓存,比如redis这样的缓存数据库,降低压力,第二步限流,使用Hystix对请求进行流量的控制,第三步,使用rabbitMq进行削峰,让一部分先查,一部分后查,如果以上还不行,那就要考虑使用nosql数据库了。

那为什么nosql数据库那么厉害,他为什么快呢,现在就来说说他为什么快,以ElasticSearch为例,他的核心是使用了倒排索引,那啥是倒排索引呢?

我们想一想mysql这种关系型数据库他是怎么查数据的,他是先找到表,他的表是B+树,然后再在这个B+树上查找我们想要查找的数据,这里我们把想要查找的数据命名为关键词,我们知道B+树的数据结构会让查找的时间复杂度优化到logn,这是在通过索引查找的基础上所得到的最优的方式,那如果是对于很大的数据量,显然还是存在不足的。
而倒排索引的数据结构就能满足我们的查询,他是通过关键词和文件进行映射来进行查找的(这个文件可以理解成mysql的表),我们知道Map映射的时间复杂度是O1,所以他当然更快。

image.png

那他具体是怎么实现的呢?他的数据结构是什么呢?

我们看一张单词-文档矩阵图

image.png

这个矩阵图表明了词汇与文档的关系,倒排索引就是通过这个来实现的

下面了解下倒排索引基本概念

文档(Document):一般搜索引擎的处理对象是互联网网页,而文档这个概念要更宽泛些,代表以文本形式存在的存储对象,相比网页来说,涵盖更多种形式,比如Word,PDF,html,XML等不同格式的文件都可以称之为文档。再比如一封邮件,一条短信,一条微博也可以称之为文档。在本书后续内容,很多情况下会使用文档来表征文本信息。
文档集合(Document Collection):由若干文档构成的集合称之为文档集合。比如海量的互联网网页或者说大量的电子邮件都是文档集合的具体例子。

文档编号(Document ID):在搜索引擎内部,会将文档集合内每个文档赋予一个唯一的内部编号,以此编号来作为这个文档的唯一标识,这样方便内部处理,每个文档的内部编号即称之为“文档编号”,后文有时会用DocID来便捷地代表文档编号。

单词编号(Word ID):与文档编号类似,搜索引擎内部以唯一的编号来表征某个单词,单词编号可以作为某个单词的唯一表征。

倒排索引(Inverted Index):倒排索引是实现“单词-文档矩阵”的一种具体存储形式,通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。

单词词典(Lexicon):搜索引擎的通常索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。

倒排列表(PostingList):倒排列表记载了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。

倒排文件(Inverted File):所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件即被称之为倒排文件,倒排文件是存储倒排索引的物理文件。

了解概念后,我们通过图示具体看下倒排索引

image.png

上图是文档编号和文档内容

image.png

上图就是取出了文档内容中单词出现再那个文章中,倒排列表中存储的就是文档编号的集合,这里面注意的是会涉及到分词,因为单词在文档中出现,怎么把单词从文档中剥离出来,就需要分词了,而分词的操作都是需要分词器来完成,这部分再具体项目中会对分词器进行选取,就不多说了。

上图中就已经实现了单词id和文档进行了映射,但是还不够,我们还要查询出单词在文档中出现的频率

image.png

上图就记录了单词在文档中出现的频率,通过频率就可以做搜索引擎对内容的排序了。

这里面还要思考一个问题,就是单词存储的是上图的形式,那么查询单词的性能还会很慢,索引就引出了单词是由什么数据结构来粗出的。也就是上面提到的概念单词词典。

对单词的保存的数据结构也有几种包括哈希加链表形式,树形的形式,这样就优化了速度。

以上就是es使用的倒排索引的数据结构,那除了倒排索引es还有什么不同呢,就是es是基于分布式存储的,他的数据可以分布到很多分片上。而分片的数量可以根据业务量进行调整,所以就不会有一个分片上存储太多数据导致查询缓慢的问题。

下面看看es是怎样查询的,先看一张图

image.png

由于es是分布式的,所以他有多个节点来进行高可用,然后如果节点挂掉了,从分片会用来记录数据,防止数据丢失。

es的查询流程是

1 当访问到A节点,A节点会把访问转接到各个分片,各个分片返回数据id,也就是字符串

2 A节点根据返回的id进行排序分页,再去根据id查询各个分片

3 各个分片根据id查询出相应的文档数据并返回给A节点

以上就是es的查询流程,看看是不是和mysql很不一样。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享