数据库索引

一、什么是索引?

举个例子:当你想去商场里看电影的时候,而此时你又不知道电影是在哪一层,更不知道是在哪一个房间,不得不需要一层一层一家一家的找。当你正准备开始找的时候发现旁边有一个牌子上面写明了一楼是卖衣服的,二楼是卖皮具的,三楼是卖玩具的,四楼是吃美食的。根据牌子上的提示,你就可以方便快捷的找到你的目的地。

例子中的牌子上的内容就是索引。在数据中,索引就是用来帮我们定位到目标数据的数据结构

二、数据库中的数据如何存储的?

数据库中的数据存储在磁盘上,想要读取数据,需要先从磁盘种取出数据拿到内存中,但是我们知道:磁盘的读写速度与内存的读写速度相差了几个数量级,速度不匹配,效率就低。
因此,如何高效地将数据从磁盘中取出到内存中是一个关键的问题。所以磁盘上将数据存储于数据页中,每个数据页的大小为16KB,这也就意味着:磁盘到内存之间传输的最小单位是16KB。这样就提高了数据传输速率。那么如何确定哪些数据是我们需要的数据呢?
这就用到了数据库引擎InnoDB,InnoDB的底层原理实际上就是B+树,InnoDB 将它称为数据库索引。通过数据库索引,可以很快的查找出我们需要的数据。

B+树的具体怎么实现?

1、数据页层面:数据页中存储着许多条完整的数据信息(按照主键大小顺序排列),对应着数据库表中的每一行数据,这其中最关键的就是主键。每一条数据之间按照主键排序,使用单链表的形式连接关联,这意味着从上一条数据可以找到下一条数据,那么多数据,我们怎样根据主键找到我们需要的那条数据呢?遍历?当然不行,这样的效率实在太低了——我们可以将这些数据分组,每一组选出主键值最大的作为组长,组长中保存着这个组中一共有多少条数据,这个组长被InnoDB成为“槽”,这样势必会得到许多个槽,槽与槽之间的物理地址是相邻的,这样保证了从上一个槽能够找到下一个槽。
在上层传来目标主键target时,通过二分法比较target与槽的编号(前面说的,组中的最大主键值),快速找到需要的数据。数据多了,一个数据页就不够存了,就需要多个数据页,多个数据页之间使用双向链表关联起来。
那么又怎么确定target位于哪个数据页中呢?又想遍历?当然不!!同理,把数据页再上升一个层次,放到数据页目录中,就像把数据页也分组,把分组结果又放到一个页中,为了区分,我们把这个页
称为目录页。不同的是,目录页中保存的每一条数据是对应的数据页数据:数据页中的最小主键值+数据页页号。
2、目录页层面:目录页中保存的每一条数据是对应的数据页数据:数据页中的最小主键值+数据页页号。
     目录页与目录页之间也通过双链表关联,目录页多了就再往上提取,提取成,根中的数据:对应的目录页中的最小主键值+目录页页码。由于树的层次过多不利于遍历效果,所以B+树上只采取了三层树结构。

图片参考:

                            (1、数据页中的槽和数据记录的对应关系)

                            (2、数据页到目录页的对应关系)

                                                 (3、B+树三层的结构)


3、至此,一共提取了3层结构,分别是:数据页层、目录页层 、存储目录页层的根。总的来看,根就类似于书架,目录页层相当于书,数据页层相当于书中的目录页,而数据页中的每一条数据记录相当于章节中的小节。
这样,假如我们要查找主键target,查找流程如下:
二分查找法从根中确定目录页-->再在目录页中二分查找法确定数据页-->数据页中二分查找法确定槽-->槽之后找到具体数据。
以上操作都是基于主键的,显然,主键是相当重要的,那么如果在创建数据库时没有设置主键,这样的搜索方式是不是就不能用了呢?
事实上,如果没有设置主键,InnoDB会首先选取Unqiue字段作为主键,如果连这个字段也没有,那会自动为每一条数据生成一个主键,但是这个主键是我们看不到的,所以,对于InnoDB来说,主键不存在的影响完全可以排除。
以上就是主键索引

 普通索引和关联索引

那么假如不根据主键查找数据呢?——普通索引和联合索引
假如我要根据非主键字段,比如name字段来查询数据,该怎么做呢?首先,InnoDB会自动生成一棵主键索引B+树,我们可以通过回表的方式来实现非主键查询数据。
你可能会想,主键索引形式的B+树效率那么高,那我们直接模拟主键索引,再建立一棵基于name属性的B+树(数据页中的数据按照name字段进行排序)不就好了吗?但你想想,一张表中那么多数据,那么多字段属性,假如按照这种方式,创建那么多棵B+树,那对于磁盘内存来说,压力多大啊。

因此,可以思路稍微转变一下:依然采取B+树的形式查询数据,但是数据页中的数据不要完整的数据内容,只需要name + 主键,数据按照name进行排序,
目录页中存储:name+主键+数据页号,这样找到对应的name对应的主键之后再通过主键索引去获取完整的数据内容——(此过程就是 “回表”),这样不就既保证了磁盘空间,又保证了查询效率吗?这就是普通索引。
联合索引:根据两个及两个以上的非主键字段进行查询。同样的道理,依然采用B+树来实现,但是数据页中存储的具体数据为:[非主键字段列表]+主键,按照非主键字段列表进行排序,目录页中存储的数据:[非主键字段列表]+数据页号。
拿到主键之后进行“回表”操作拿到完整的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值