一、何为索引?

1、索引是帮助数据库高效获取数据的排好序的数据结构。

2、索引存储在文件中。

3、索引建多了会影响增删改效率。(一张表最多允许建16个索引)

(下面这张图为计算机组成原理内容,每查询一次索引节点,都会进行一次磁盘IO读取,即要寻道和旋转)

二、MySQL索引结构为什么是B+树?

MySQL 建索引可使用的数据结构有B+树和Hash两种,但是Hash用得很少, 优点是可以快速定位到某一行,缺点是不能解决范围查询问题。

对于如果不需要使用范围查询、只需要精准查询的场景,可以使用Hash索引方法,比如查电话号码。

再说说主流的索引方法B+树,先说下为什么不用别的树结构,再说为什么用B+树。

1、为什么不用二叉树?

如果碰到下面这种单边增长的极端情况,查找节点4和顺序查找没区别。(这种特殊情况的二叉树等同于链表,时间复杂度为O(n))

2、为什么不用红黑树?

红黑树是一颗平衡二叉树,数据量大的时候,树的深度也很深,如果树的深度有20层,而查找的数据在叶子节点,就要进行20次IO操作,性能低。

3、为什么不用B树?

B树的特点:

叶子节点具有相同的深度

叶子节点的指针为空

叶子节点中的数据key从左到右递增排列

其实B树就是在横向做了文章,一个节点可以存储更多数据(大节点包含很多小节点),这样相对来说,深度就会变浅。

提问:横向的节点怎么查,比如说查找上图中的节点77?

从磁盘中把大节点查找出来,把这个大节点加载进内存中,节点77实际上是在内存中查找的,在内存中做的是随机访问,速度很快,跟磁盘的寻道和旋转相比的话,基本可以忽略不计。

提问:为什么不可以让B树横向的度无限增大,这样不就深度为1,查找不就更快了?(度的含义:节点的数据存储个数)

本来是想通过一次IO操作把一个大节点加载进内存,如果一个大节点的数据量太大的话, 则内存和硬盘一次交互没办法交换那么多数据,假设一次只能交换1页(4k)的数据(有上限,也有可能是几十页,和计算机硬件有关),意味着CPU去硬盘上做一次IO操作只能取1页的数据,那么当一个大节点的数据量太大时,仍要进行多次IO操作。因此,度是有上限的,MySQL会根据计算机硬件自动进行度的优化,一个大节点通常为1页空间。

4、为什么使用B+树?(B+树是B树的变种,索引做了冗余,存了多份,但是没关系,索引只占很小空间,比如下图中的15节点)

B+树的特点:

非叶子节点不存储data,只存储key,可以增大度(相比B树,B+树的深度更浅)

叶子节点不存储指针

顺序访问指针,提高区间访问的性能(实际上是双向指针)

提问:为什么说B+树可以增大度?

因为非叶子节点只存储索引一个值,不存储data(B树会存储data),而大节点大小是确定的,因此大节点就可以存储更多的数据,即度可以变得更大。这样既保证度可以达到最大,又保证一个大节点通过一次IO操作可以加载进内存。(非叶子节点度更大,深度更浅,只有非叶子节点才影响查找次数,叶子节点是最后一次查找,对总的查找次数是没有影响的,因此把data全部移到了叶子节点)

提问:为什么叶子节点之间还需要用指针?(一个大节点的尾节点和下一个大节点的头节点之间的指针连接)

方便范围查询。比如查找上图中key>18,如果没有指针会非常麻烦,必须从头开始查找,如果有指针,则可以直接遍历key>18的叶子节点(链表)。

B+树索引的性能分析:

一般使用磁盘I/O次数评价索引结构的优劣

预读:磁盘一般会顺序向后读取一定长度的数据(页的整数倍)放入内存

局部性原理:当一个数据被用到时,其附近的数据也通常会立马被使用

B+树的大节点大小设为等于一个页,每次新建大节点直接申请一个页的空间,这能保证一个大节点物理上也存储在一个页里,大节点载入只需一次IO操作

B+树的度d一般会超过100,因此高度h非常小(一般为3~5之间)

三、MySQL底层是怎么用B+树来存储数据的?

MySQL有两种常见的存储引擎:InnoDB(默认)、MyISAM(用得少,在MySQL8.0中被废弃掉了),存储引擎范围是表级别的。

1、MyISAM索引实现(非聚集)

索引文件和数据文件是分离的

索引结构的叶子节点value存储的是文件指针。

.frm是表结构文件,.MYD是数据文件(MyISAM Data),.MYI是索引文件(MyISAM Index)。

MyISAM主键索引查找流程:先通过.MYI文件找到对应索引的文件指针,再根据文件指针去.MYD文件中定位对应的那行数据。

MyISAM普通索引查找流程:和主键索引查找流程一致。

2、InnoDB索引实现(聚集)

数据文件本身就是索引文件

表数据文件本身就是按B+树组织的一个索引结构文件

聚集索引的叶子节点包含了完整的数据记录

表必须有主键,且推荐使用整型的自增主键

普通索引结构叶子节点存储的是主键值

.frm是表结构文件,.ibd是数据和索引文件(InnoDB Data)

InnoDB主键索引查找流程:通过.ibd文件找到对应的索引,索引的value即为那行对应的完整数据。

InnoDB普通索引查找流程:通过.ibd文件找到对应的索引,索引的value即为那行对应的主键的值,再根据主键值去主键索引树中找到对应的行数据。

提问:聚集索引和非聚集索引的区别?

聚集索引:表中那行数据的索引和数据都合并在一起了。

非聚集索引:表中那行数据的索引和数据是分开存储的。

提问:为什么InnoDB表必须有主键?

因为整个数据文件本身就是按照B+树组织的一个索引文件,所以必须要有主键(建InnoDB表时不指定主键,默认会从表字段中选一列作为唯一主键,如果不存在这种字段,则后台默认生成一个长整型主键字段,MyISAM可以没有)。

提问:为什么推荐使用整型的自增主键?

提高查询性能。如果是使用UUID作为主键,第一,UUID长度很长,会浪费存储空间,第二,UUID是字符串类型,比较大小要查找ASCII码表,查找速度没有整型int查找速度快,第三,UUID是随机生成无序的字符串,当数据插入时,有很大可能会导致节点位置移动,还可能造成很多其他节点位置移动,简单来说就是位置打乱了。 如果使用整型的自增主键,新插入的数据都会连续的插入到磁盘的物理空间。

提问:为什么InnoDB普通索引结构叶子节点存储的是主键值?(一致性和节省存储空间)

如果普通索引的value也存数据,那么当往有主键索引和普通索引的表中插入数据时,索引结构中key对应的value要存储两份数据,增加维护成本。

单值索引:只有一个索引,如(id),size=1

联合索引:多个索引合起来作为一个联合索引,如(id,name),size>1(单值索引是联合索引size=1的特例)

提问:联合索引的底层数据结构长什么样?

(叶子节点key是联合索引值,value是除联合索引以外一行记录其他字段的完整数据)

先比较id,如果id相等,再比较name,如果name也相等,则再比较date。(索引最左前缀原理,后面索引优化随笔会讲解)

mysql索引底层图_MySQL索引底层数据结构相关推荐

  1. mysql b tree图_MySQL索引--B-Tree(B+Tree)图文详解

    看了很多关于索引的博客,讲的大同小异.但是始终没有让我明白关于索引的一些概念,如B-Tree索引,Hash索引,唯一索引....或许有很多人和我一样,没搞清楚概念就开始研究B-Tree,B+Tree等 ...

  2. mysql索引原理传送门_MySQL索引底层实现原理

    索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 我们知道,数据库查询是数据库的最主要功能之一. ...

  3. mysql设置索引树长度_MySQL索引-B+树

    索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的数据. 索引最形象的比喻就是图书的目录了.注意这里的大量,数据量大了索引才显得有意义,如果我想要在 [1,2,3,4] 中找到 4 ...

  4. mysql索引实现原理_Mysql索引原理

    1.二分查找法 二分法,也叫二分查找法,是一种高效的查找算法. 如下一个有序数列,如果我们需要从中找到1这个元素,这个过程需要查找几次? [1,2,3,4,5,6,7,8,9,10] 对于这个数列查找 ...

  5. mysql索引优化分析_MySQL索引优化与分析(重要)

    建表SQL CREATE TABLE staffs ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR (24) NULL DEFAULT '' COM ...

  6. mysql 二叉树表设计_Mysql 索引模型 B+ 树详解

    一.认识二叉树 首先,在了解 mysql 中的 B+ 树之前,我们需要搞懂什么是二叉树.二叉树是一种常见的非线形数据结构,数据是以一对多的形态组织起来的,我画了一张图来帮助你理解: 在二叉树中,有一种 ...

  7. mysql 索引生命周期_MYSQL 索引(一)--- 简介

    简介 Mysql 官方定义 : 索引(Index) 是帮助 Mysql 高效获取数据的数据结构. 索引的目的在于提交查询效率,可以类比字典.简单理解为 "排好序的快读查找数据结构" ...

  8. mysql b 树 锁_mysql索引B+树、MVCC、锁一文搞懂

    1.innodb索引 innodb是页存储,一页是16K. 一个表的行数据都放到页里,单页都是单链表递增排序. 每个页之间都是双向链表保存.该页标记成数据页. 根据id查询时,也不知道在哪个数据页上. ...

  9. mysql索引条件下推_MySQL 索引条件下推优化

    一 什么是"索引条件下推" "索引条件下推",称为Index Condition Pushdown (ICP),这是MySQL提供的用某一个索引对一个特定的表从 ...

最新文章

  1. Python中怎么判定一个List里面的元素是不是全部一样
  2. OpenCV之gpu 模块. 使用GPU加速的计算机视觉:GPU上的相似度检测(PNSR 和 SSIM)
  3. dom定义了访问html文档对象的,HTML DOM (文档对象模型)
  4. win7win10 配置wlan热点
  5. Nova虚拟机启动提示libvirtError
  6. 数据结构:链表(c语言)
  7. 才27岁,北大博士不幸离世
  8. codeigniter mysql查询_php – CodeIgniter MySQL查询不起作用
  9. 蔡高厅老师 - 高等数学-阅读笔记 - 01 - 前言、函数【视频第01、02、03、】
  10. 基于Xilinx Spartan-7 FPGA实现AD7606-8接口
  11. Python-Matplotlib 12 多图figure
  12. 支付宝小程序框架分析
  13. xwt100编程器使用方法与xtw100没有找到编程器解决办法
  14. 使用 jszip 实现.zip文件解压后上传
  15. 基于GPT2实现考公申论文章生成
  16. 如何抢功,甩锅,立于不败之地???
  17. 学数答题160912-导数极值点偏移
  18. 中小学数学卷子自动生成程序
  19. 20191025 前端开发日报
  20. Centos7 设置开机自启的几种方式

热门文章

  1. Extension project: 404 Not Found for resources/cus/crm/notes/ext/Component-dbg.js
  2. 使用application log 分析navigation target解析错误
  3. SAP CRM interaction center呼叫中心的一些性能问题的分析
  4. How AET fields are retrieved from backend
  5. ABAP Business switc和business function简介
  6. Java Spring实现原理研究之Servlet initialization初始化过程
  7. 前端开发神器Sublime里如何设置JSlint
  8. SAP Cloud for Customer的前端框架是如何基于SAP UI5框架开发的
  9. SAP CDS view性能调优的一些准则和例子
  10. python 连通域_连通域的原理与Python实现