MySQL01-引擎索引与基础数据结构

喋喋不休
• 阅读 1452

MySql引擎比较

  • 在介绍MySql索引以及底层数据结构之前想先对比一下MySql的几种存储引擎
功能/索引 MyISAM InnoDB MEMORY
索引类型 非聚簇索引 聚簇索引 Hash
存储限制 256TB 64TB RAM
支持事务 No Yes No
支持表锁 Yes Yes None
支持行锁 No Yes None
支持全文索引 Yes Yes(5.6以后支持) No
支持树索引 Yes Yes Yes
支持Hash索引 No No Yes
支持数据缓存 No Yes N/A
支持外键 No Yes No
适合操作类型 大量select 大量insert、delete、update 非持久化

基础数据结构介绍

基础数据类型介绍:
1. AVL树(二叉平衡搜索树,所有节点左右子树高度差不超过1)
2. 红黑树(最深子树高度不会超过最浅子树高度的2倍)
3. B树
4. B+树
5. Hash
最好的演示网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

MySql数据结构的选择

首先来分析一下几种基础数据类型

1. Hash表的索引格式

MySQL01-引擎索引与基础数据结构

Hash表的索引格式首先需要计算Hash值,然后用mod方法确定值存储的位置,如果该位置已经有值,那就是Hash冲突,需要在该值下面的链表尾添加数据

缺点:

1、利用hash存储的话需要将所有的数据文件添加到内存,比较耗费内存空间
2、如果所有的查询都是等值查询,那么hash确实很快,但是在企业或者实际工作环境中范围查找的数据更多,而不是等值查询,因此hash就不太适合了

2. 二叉树和红黑树的索引

二叉树比较简单,介绍一下红黑树特点

红黑树特点:
1. 每个节点非红即黑
2、根节点是黑色
3、每个叶节点(叶节点即树尾端NULL指针或NULL节点)都是黑的
4、如图所示,如果一个节点是红的,那么它的两个儿子都是黑的
5、对于任意节点而言,其到叶子节点树NULL指针的每条路径都包含相同数目的黑节点
6、每条路径都包含相同的黑节点
7、红黑树确保没有一条路径会比其他路径长出两倍

MySQL01-引擎索引与基础数据结构

1、二叉树每个节点的左子树上的值都小于该节点,右子树的值都大于该节点,如果频繁插入和删除节点,最后二叉树就会退化为一个拍好序的链表,而影响查找
2、AVL严格平衡二叉树,节点删除和插入时都需要通过旋转来保持二叉树的平衡性,所有叶子节点的高度差不超过1,AVL保持了良好的查找特性,但是插入和删除的旋转操作复杂且耗时,所以AVL树只适合大量查找,但是修改不频繁的场景
3、红黑树是一种简化后的二叉树,它的要求没有那么严格,最深子树高度不会超过最浅子树高度的2倍

缺点:

无论是二叉树还是红黑树,都会因为树的深度过深而造成io次数变多,影响数据读取的效率

3. B树索引格式

B树特点:
1、所有键值分布在整颗树中
2、搜索有可能在非叶子结点结束,在关键字全集内做一次查找,性能逼近二分查找
3、每个节点最多拥有m个子树
4、根节点至少有2个子树
5、分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点)
6、所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列

MySQL01-引擎索引与基础数据结构

实例图说明:
每个节点占用一个磁盘块,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为 16 和 34,P1 指针指向的子树的数据范围为小于 16,P2 指针指向的子树的数据范围为 16~34,P3 指针指向的子树的数据范围为大于 34。 

查找关键字过程:
1、根据根节点找到磁盘块 1,读入内存。【磁盘 I/O 操作第 1 次】
2、比较关键字 28 在区间(16,34),找到磁盘块 1 的指针 P2。
3、根据 P2 指针找到磁盘块 3,读入内存。【磁盘 I/O 操作第 2 次】
4、比较关键字 28 在区间(25,31),找到磁盘块 3 的指针 P2。
5、根据 P2 指针找到磁盘块 8,读入内存。【磁盘 I/O 操作第 3 次】
6、在磁盘块 8 中的关键字列表中找到关键字 28。 

缺点:

1、每个节点都有key,同时也包含data,而每个页存储空间是有限的,如果data比较大的话会导致每个节点存储的key数量变小
2、当存储的数据量很大的时候会导致深度较大,增大查询时磁盘io次数,进而影响查询性能

4. MySql索引数据结构--B+Tree

B+Tree是在BTree的基础之上做的一种优化,变化如下:
1、B+Tree每个Key右边的子节点是大于等于该节点的值,这样就可以把Data都存在叶子节点
2、B+Tree每个节点可以包含更多的节点,这个做的原因有两个,第一个原因是为了降低树的高度,第二个原因是将
数据范围变为多个区间,区间越多,数据检索越快
3、非叶子节点存储key,叶子节点存储key和数据
4、叶子节点两两指针相互连接(符合磁盘的预读特性),顺序查询性能更高

MySQL01-引擎索引与基础数据结构
注意:

在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

InnoDB的B+Tree索引

1、InnoDB是通过B+Tree结构对主键创建索引,然后叶子节点中存储记录,如果没有主键,那么会选择唯一键,如果没有唯一键,那么会生成一个6位的row_id来作为主键(主键索引不允许为空,唯一索引允许为空
2、如果创建索引的键是其他字段,那么在叶子节点中存储的是该记录的主键,然后再通过主键索引找到对应的记录,叫做回表

索引中的常见技术名词

1. 回表

对于普通列的索引,其B+树的叶子节点存储的不是整行的值,而是主键的值,先找到普通索引值,然后再通过主键的B+树查找到整行的值,这个过程称为回表

2. 覆盖索引

如果查询所需要的值就只有主键值,那么通过普通列索引搜索B+树最后得到的就是所需值,不需要回表,这个就称为覆盖索引

3. 最左匹配

where条件中的字段值必须按照索引顺序,不能跳过某个值
例如:name age是索引
select * from emp where name=?(索引生效)
select * from emp where age=?(索引不生效)

4. 索引下推

索引在最初查询时已经经过筛选,不需要在Server再做计算
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
3年前
Jira 使用手册
<tablestyle"width:100%;margin:200px0300px0;"<tr<thDate</th<thRevisionversion</th<thDescription</th<thauthor</th</tr<tr<td20180614</td<tdV1.0.0</td
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
MySQL数据库InnoDB存储引擎Log漫游(1)
作者:宋利兵来源:MySQL代码研究(mysqlcode)0、导读本文介绍了InnoDB引擎如何利用UndoLog和RedoLog来保证事务的原子性、持久性原理,以及InnoDB引擎实现UndoLog和RedoLog的基本思路。00–UndoLogUndoLog是为了实现事务的原子性,
Stella981 Stella981
3年前
ELK学习笔记之ElasticSearch的索引详解
0x00ElasticSearch的索引和MySQL的索引方式对比Elasticsearch是通过Lucene的倒排索引技术实现比关系型数据库更快的过滤。特别是它对多条件的过滤支持非常好,比如年龄在18和30之间,性别为女性这样的组合查询。倒排索引很多地方都有介绍,但是其比关系型
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这