mysql索引 和 es索引_MySQL索引 VS ElasticSearch索引

今天MySQL数据库栏目介绍MySQL索引与ElasticSearch索引的对比。530c8a775e5f64c4b2730af2c5c25147.png

前言

这段时间在维护产品的搜索功能,每次在管理台看到 elasticsearch 这么高效的查询效率我都很好奇他是如何做到的。8e608877257a4a17103fd3581377100d.png

这甚至比在我本地使用 MySQL 通过主键的查询速度还快。b3f54324b8f3c1ab7e94e27521a12a49.png

为此我搜索了相关资料:1d75b47d10794ae9566a76632a96e150.png

这类问题网上很多答案,大概意思呢如下:ES 是基于 Lucene 的全文检索引擎,它会对数据进行分词后保存索引,擅长管理大量的索引数据,相对于 MySQL 来说不擅长经常更新数据及关联查询。

说的不是很透彻,没有解析相关的原理;不过既然反复提到了索引,那我们就从索引的角度来对比下两者的差异。

MySQL 索引

先从 MySQL 说起,索引这个词想必大家也是烂熟于心,通常存在于一些查询的场景,是典型的空间换时间的案例。以下内容以 Innodb 引擎为例。复制代码

常见的数据结构

假设由我们自己来设计 MySQL 的索引,大概会有哪些选择呢?

散列表

首先我们应当想到的是散列表,这是一个非常常见且高效的查询、写入的数据结构,对应到 Java 中就是 HashMap943a9fb2387d7dffa0fd5f84fecdb62b.png

这个数据结构应该不需要过多介绍了,它的写入效率很高O(1),比如我们要查询 id=3 的数据时,需要将 3 进行哈希运算,然后再这个数组中找到对应的位置即可。

但如果我们想查询 1≤id≤6 这样的区间数据时,散列表就不能很好的满足了,由于它是无序的,所以得将所有数据遍历一遍才能知道哪些数据属于这个区间。

有序数组4f2bdccee85bbad8d48477c0b4a96834.png

有序数组的查询效率也很高,当我们要查询 id=4 的数据时,只需要通过二分查找也能高效定位到数据O(logn)。

同时由于数据也是有序的,所以自然也能支持区间查询;这么看来有序数组适合用做索引咯?

自然是不行,它有另一个重大问题;假设我们插入了 id=2.5 的数据,就得同时将后续的所有数据都移动一位,这个写入效率就会变得非常低。

平衡二叉树

既然有序数组的写入效率不高,那我们就来看看写入效率高的,很容易就能想到二叉树;这里我们以平衡二叉树为例:bd2baf5e63c2b873b94f5331e6400c24.png

由于平衡二叉树的特性:左节点小于父节点、右节点大于父节点。

所以假设我们要查询 id=11 的数据,只需要查询 10—>12—>11 便能最终找到数据,时间复杂度为O(logn),同理写入数据时也为O(logn)。

但依然不能很好的支持区间范围查找,假设我们要查询5≤id≤20 的数据时,需要先查询10节点的左子树再查询10节点的右子树最终才能查询到所有数据。

导致这样的查询效率并不高。

跳表

跳表可能不像上边提到的散列表、有序数组、二叉树那样日常见的比较多,但其实 Redis 中的 sort set 就采用了跳表实现。

这里我们简单介绍下跳表实现的数据结构有何优势。

我们都知道即便是对一个有序链表进行查询效率也不高,由于它不能使用数组下标进行二分查找,所以时间复杂度是o(n)

但我们也可以巧妙的优化链表来变相的实现二分查找,如下图:c8d71e635d199751200f83308360c27e.png

我们可以为最底层的数据提取出一级索引、二级索引,根据数据量的不同,我们可以提取出 N 级索引。

当我们查询时便可以利用这里的索引变相的实现了二分查找。

假设现在要查询 id=13 的数据,只需要遍历 1—>7—>10—>13 四个节点便可以查询到数据,当数越多时,效率提升会更明显。

同时区间查询也是支持,和刚才的查询单个节点类似,只需要查询到起始节点,然后依次往后遍历(链表有序)到目标节点便能将整个范围的数据查询出来。

同时由于我们在索引上不会存储真正的数据,只是存放一个指针,相对于最底层存放数据的链表来说占用的空间便可以忽略不计了。

平衡二叉树的优化

但其实 MySQL 中的 Innodb 并没有采用跳表,而是使用的一个叫做 B+ 树的数据结构。

这个数据结构不像是二叉树那样大学老师当做基础数据结构经常讲到,由于这类数据结构都是在实际工程中根据需求场景在基础数据结构中演化而来。

比如这里的 B+ 树就可以认为是由平衡二叉树演化而来。

刚才我们提到二叉树的区间查询效率不高,针对这一点便可进行优化:11d40a5ba5786ac23e46eabbec791784.png

在原有二叉树的基础上优化后:所有的非叶子都不存放数据,只是作为叶子节点的索引,数据全部都存放在叶子节点。

这样所有叶子节点的数据都是有序存放的,便能很好的支持区间查询。

只需要先通过查询到起始节点的位置,然后在叶子节点中依次往后遍历即可。

当数据量巨大时,很明显索引文件是不能存放于内存中,虽然速度很快但消耗的资源也不小;所以 MySQL 会将索引文件直接存放于磁盘中。

这点和后文提到 elasticsearch 的索引略有不同。

由于索引存放于磁盘中,所以我们要尽可能的减少与磁盘的 IO(磁盘 IO 的效率与内存不在一个数量级)

通过上图可以看出,我们要查询一条数据至少得进行 4 次IO,很明显这个 IO 次数是与树的高度密切相关的,树的高度越低 IO 次数就会越少,同时性能也会越好。

那怎样才能降低树的高度呢?4533f7abefe4f0399c9ea2a337b86226.png

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

使用索引的一些建议

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

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

如果是按照递增写入数据时则不会有这个考虑,每次只需要依次写入即可。所以我们才会要求数据库主键尽量是趋势递增的,不考虑分表的情况时最合理的就是自增主键。

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

ES 索引

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

正排索引

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

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

比如通过 doc_id=4 便能很快查询到 name=jetty wang,age=20 这条数据。

倒排索引

那如果反过来我想查询 name 中包含了 li 的数据有哪些?这样如何高效查询呢?

仅仅通过上文提到的正排索引显然起不到什么作用,只能依次将所有数据遍历后判断名称中是否包含 li ;这样效率十分低下。

但如果我们重新构建一个索引结构:7103317001bc686abb32a6d94c679157.png

当要查询 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。e011d090514a91e2b0202f3f77db5695.png

这个 Term Index 我们可以使用这样的 Trie树 也就是我们常说的字典树 来存放。

更多关于字典树的内容请查看这里。8dd3b2ab7fc44940efdcb788d0e9e0bb.png

如果我们是以 j 开头的 Term 进行搜索,首先第一步就是通过在内存中的 Term Index 查询出以 j 打头的 Term 在 Term Dictionary 字典文件中的哪个位置(这个位置可以是一个文件指针,可能是一个区间范围)。

紧接着在将这个位置区间中的所有 Term 取出,由于已经排好序,便可通过二分查找快速定位到具体位置;这样便可查询出 Posting List。

最终通过 Posting List 中的位置信息便可在原始文件中将目标数据检索出来。

更多优化

当然 ElasticSearch 还做了许多针对性的优化,当我们对两个字段进行检索时,就可以利用 bitmap 进行优化。

比如现在需要查询 name=li and age=18 的数据,这时我们需要通过这两个字段将各自的结果 Posting List 取出。e0e764e2b7ce6ceda18da99dc61fcab2.png

最简单的方法是分别遍历两个集合,取出重复的数据,但这个明显效率低下。

这时我们便可使用 bitmap 的方式进行存储(还节省存储空间),同时利用先天的位与 **计算便可得出结果。**

[1, 3, 5] ⇒ 10101

[1, 2, 4, 5] ⇒ 11011

这样两个二进制数组求与便可得出结果:

10001 ⇒ [1, 5]

最终反解出 Posting List 为[1, 5],这样的效率自然是要高上许多。

同样的查询需求在 MySQL 中并没有特殊优化,只是先将数据量小的数据筛选出来之后再筛选第二个字段,效率自然也就没有 ES 高。

当然在最新版的 ES 中也会对 Posting List 进行压缩,具体压缩规则可以查看官方文档,这里就不具体介绍了。

总结

最后我们来总结一下:3fa3c90b9c7dcc2d35a5a064f8fef1c4.png

通过以上内容可以看出再复杂的产品最终都是基础数据结构组成,只是会对不同应用场景针对性的优化,所以打好数据结构与算法的基础后再看某个新的技术或中间件时才能快速上手,甚至自己就能知道优化方向。

最后画个饼,后续我会尝试按照 ES 倒排索引的思路做一个单机版的搜索引擎,只有自己写一遍才能加深理解。相关免费学习推荐:mysql数据库(视频)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489774.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开启httponly之后登陆失败_二次元约会模拟《少女都市》正式版登陆Steam 橘势大好...

《少女都市(Shoujo City)》于2018年1月在Steam开启了抢先测试,昨天发布了1.0正式版。这是一款专注于二次元和御宅文化的百合向约会模拟游戏,目前Steam好评率94%,自带简体中文。《少女城市》结合了美少女视觉小说与沙盒式的城市探索冒险&#…

科技/IT:2019 年 Q3 表现最佳和最差的企业

来源:云头条在2019年上半年经历稳步上涨之后,由于全球经济的不确定性和美中贸易紧张局势,2019年第三季度的股市如同过山车。道琼斯指数第三季度(截至9月30日)以26916.83点收盘,比2019年6月28日收盘价上涨1.…

java图片压缩不失真_软件分享 | Lit图片压缩

软件分享01软件名称Lit图片压缩02软件版本V1.2.0.01603软件简介Lit图片压缩app是一款免费简单好用的图片压缩工具,让图片在不失真的情况下,进行压缩和裁剪,轻松就能压缩成你想要的尺寸,并且原来的像素不失真,保持原画质…

从大型主机到个人计算机:机器人产业可以从pc普及革命中学到什么?

来源:大数据文摘出品自主化机器人已逐渐变得无处不在。自动吸尘器、自动割草机、会简单交互的小玩具,以及呼之欲出的自动驾驶汽车,都可以看作是一个能实现某种自动功能的机器人。一辈接着一辈,我们一直在期待出现《星球大战》中的…

【Poj1017】Packets

http://poj.org/problem?id1017 艰难啊 弄了很久咧 拍了几十万组,以后拍要多组数据 Solution 从大wangxiaofang 从大往小放,有空余的从大往小填 注意细节 Notice b<0的情况,还有就是当前填充完了,还剩一点给下一个(小一点的)填 Code // This file is made by YJinpeng&…

构建超级智能未来系统的三原则

《崛起的超级智能》作者&#xff0c;计算机博士刘锋前言&#xff1a;科技领域看不见的手在过去50年促使互联网从网状结构进化成为大脑模型&#xff0c;而人类群体智慧与机器群体智能通过这个互联网大脑架构形成人类前所未有的超级智能形式。在构建互联网大脑模型成熟状态的过程…

游戏“冰川滑行”设计稿(第一版)

名称&#xff1a;&#xff08;暂定&#xff09;冰川滑行 游戏类型&#xff1a;关卡式迷宫 基本规则&#xff1a;在迷宫中可以向上下左右方向移动&#xff0c;每次移动只能在碰到障碍物或到达无冰区停止&#xff1b;从入口进入&#xff0c;从出口离开为胜利。 地形种类&#xff…

spring的aop_Spring AOP 小结

1. AOP专业概述在软件行业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意思为&#xff1a;面向切面编程&#xff0c;通过预编译方法和运行期动态代理实现程序功能的统一维护的一种技术。要理解切面变成&#xff0c;就需要先理解什么是切面。用刀把一个西瓜…

【解析】工业机器人中的各类传感器技术应用

来源&#xff1a;中国机器人网前言工业机器人涉及到的传感器有哪些&#xff1f;2012年&#xff0c;美国提出“工业互联网”&#xff0c;2013年&#xff0c;德国提出“工业4.0”&#xff0c;2015年&#xff0c;中国提出“中国制造2025”。在工业物联网、AR、云计算等技术热潮下&…

java水果超市mysql_Java基础 | 项目实战之水果超市

传智播客线上平台博学谷启动项目实战&#xff0c;在学习过程中真正还原企业实际开发流程及团队配合&#xff0c;同时对所学知识最大化吸收项目启动准备01规定学习位置参加项目实战&#xff0c;学习位置不能小于当前标注的位置02项目分组本次Java基础参加项目实战的同学较多&…

android dp sp px_Android屏幕适配★★重点盘点★★

引言屏幕适配是 android 开发/面试 绕不开的一个问题。本文 将屏幕适配的知识要点完整展现给各位读者。正文大纲android需要做屏幕适配的原因基础知识点(★★★很重要★★★)屏幕适配攻略正文↓↓↓android需要做屏幕适配的原因关键字&#xff1a;android碎片化android面世以来…

AI与网络安全的未来:数据集与协同能力

来源&#xff1a;安全牛有关 AI 优势与风险的争论如今已成媒体日常&#xff0c;很多此类讨论都集中在潜在负面影响上&#xff0c;话题范围从工作自动化导致广泛失业到 AI 用于创建 “深度伪造” 视频。但另一方面&#xff0c;我们已经在享受 AI 自动化助手的正面效果所带来的种…

ucinet计算聚类系数大于1怎么办_聚类性能评估-ARI(调兰德指数)

注意&#xff1a;ARI取值范围为[-1,1]&#xff0c;值越大越好&#xff0c;反映两种划分的重叠程度&#xff0c;使用该度量指标需要数据本身有类别标记。用C表示实际的类别划分&#xff0c;K表示聚类结果。定义a 为在C中被划分为同一类&#xff0c;在K中被划分为同一簇的实例对数…

这才是未来真正的风口,一文看清13种硬科技投资趋势

来源&#xff1a;资本实验室如果非要说“风口”&#xff0c;那么在未来10年乃至20年&#xff0c;硬科技就是最大的风口。近期&#xff0c;由麻省理工学院创建的非盈利投资机构The Engine与投资研究机构Pitchbook联合发布了一份名为《2019硬科技图景》的研究报告。该报告将硬科技…

mysql 滚屏查看查询结果_MySQL_查询操作(select)

查询操作1、别名查询select id 序号,name名字from test_1209ryc;2、条件查询(between)select * from test_1209ryc where id between 2 and 5;3、条件查询(in)select * from test_1209ryc where id in(1,2,3);4、子查询select * from test_1209ryc where id in (select id from…

new arraylist内存_如何避免内部类中的内存泄漏

我先假设读者已经熟悉在Java代码中使用嵌套类的基础知识。在本文里&#xff0c;我将展示嵌套类的陷阱&#xff0c;内部类在JVM中引起内存泄漏和内存不足错误的地方。之所以会发生这种类型的内存泄漏&#xff0c;是因为内部类必须始终能够访问其外部类。从简单的嵌套过程到内存不…

马斯克:“星链”卫星已能提供服务

来源&#xff1a;一财网美国太空探索技术公司首席执行官埃隆马斯克22日称&#xff0c;该公司发射的“星链”卫星已能提供天基互联网服务。马斯克当天在社交媒体推特上发布的一条推文中说&#xff0c;“正在通过‘星链’卫星发送这条推文”。2分钟后&#xff0c;他发推文表示&am…

sqlplus连mysql库_sqlplus连接数据库

sqlplus连接到远程数据库我一直以为sqlplus是服务器端的软件&#xff0c;今天我才知道sqlplus是客户端软件&#xff0c;用sqlplus也能连接到远程数据库。windows下具体连接方法如下&#xff1a;如果已经配置过tnsname方法一.在运行或者命令窗口里面先输入sqlplus/n...文章张振磊…

OpenGL ES入门

OpenGL ES渲染管线概述 渲染管线一般是由显示芯片GPU内部处理图形信号的并行处理单元组成&#xff0c;这些并行处理单元之间是独立的&#xff0c;从另一个角度看&#xff0c;渲染管线实际上也是一系列绘制过程&#xff0c;这一系列过程的输入是待绘制物体的相关描述信息&#x…

【前沿】MIT搞了个进取型机器人!能研究学习对象操纵的基础

来源&#xff1a;中国机器人网 前言&#xff1a;MIT的研究让数据有了机器人的方向麻省理工学院的研究人员已经汇编了一个数据集&#xff0c;该数据集捕获了物理上推动数百个不同对象的机器人系统的详细行为。研究人员可以使用数据集&#xff08;同类中规模最大&#xff0c;种类…