MySql存储引擎,查询是否命中索引,存储数据结构的过程演变B+Tree,事务隔离级别带来的影响,截图案例

MySql高级教程
MySql的存储引擎有哪些?
    我们可以使用SHOW ENGINES; 命令 来查询当前MySql版本支持那些存储引擎,不过在日常当中,用的最多的还是InnoDB,MyISAM,如果你是DBA 那么建议你全部去学习一下
聚集索引(叶子节点存储得是索引+数据并且每个叶子节点得指针指向后面相邻得节点),非聚集索引(叶子节点存储得是 地址或者是数据地址或者是索引得指针,并没有存储真实得数据)
常用的存储引擎InnoDB和MyISAM对比
标注:  mysql默认存储引擎 低版本是 MyISAM 高版本是InnoDB
~
MyISAM
InnoDB
索引类型
非聚簇索引
聚簇索引
支持事务
支持表锁
支持行锁
支持外键
支持全文索引
适合操作类型
大量select,insert 锁整个表
1.因为写入是 锁表 所以批量写入超级快,
2.写完了用一个变量保存整个表的行数,查询也快
业务系统
标注: 两个存储引擎,存储数据的方式都是B+Tree ,但是呢 MyISAM 叶子节点存储的是 地址X00112,而InnoDB 根节点存储冗余索引-叶子节点存储 索引+数据 并且每个儿叶子节点都会有前后叶子节点的指针,如果你创建的是非主键索引,那么叶子叶子节点存储的就只有主键索引的值而没有数据,最终拿到主键索引值 继续去查询三次IO操作,(接下来我会去讲)
 
MySql都支持那些索引呢?
首先索引是存储在磁盘上的,而且为什么需要使用索引,可以看下图:如果不用索引那么就会一行一行的读取,用了索引就可以使用二分查找法进行查找,性能也就提高了N倍
    mysql目前索引类型有五种,主键索引,唯一索引,普通索引,全文索引,组合索引,
主键索引:
    不可为空且唯一的索引,必须指定Primary Key ,MySql存储数据结构的索引,每个表只能一个主键
唯一索引:
    索引列 所有值只能出现一次 必须唯一 ,可以为空 主键其实默认也会创建唯一索引
普通索引:
    基本索引类型。值可以为空,没有唯一的限制
全文索引:
    性能差,不讲  一般都会用ElasticSearch
组合索引:
    多列组成的索引,一般都是强烈组合的查询
 
如何知道自己写的sql是否命中索引了呢?
    一、我们只要在你写的sql前面增加  explain 关键字就可以了,例如下图:可以看到 Key 是空的表示没有命中索引
解释:
1. possible_keys:显示可能应用在这条sql上的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
2. key:实际使用的索引,若为null,则没有使用到索引。(两种可能,①没建立索引。②建立索引,但索引失效)。查询中若使用了覆盖索引,则该索引仅出现在key列表中。
3. key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确型的情况下,长度越短越好,key_len显示的值为索引字段的最大可能长度,并非实际使用长度,
    二、我们测试一下命中主键索引的:如下图可看到 Key 的值不为空 而且显示的是PrimaryKey 这表示已经命中主键索引
    三、 我们创建一个联合索引,如下图:可以看到是name 和age 一起创建的联合索引,
 
    三.一 接下来我们测试 如何查询可以命中 联合(组合)索引,首先我们测试用正常的顺序 去查询where 条件后 跟着 name 和age 如下图:
    三.二 接下来我们测试单查询name 是否会命中索引:如下图: 是可以的
     三.三 那么单查询 age呢? 可以看到是没有命中索引的
注意:现在我在原来的组合索引上 增加一列  之前是 name ,age 现在是name,age,address
然后我们在把刚才的sql 拿过来测试 单独查询age 可以看到是命中索引的
三个字段组合索引 怎么查询都能查询到,这是MySql的索引优化策略
 
MySql存储数据的结构为什么使用B+Tree
一、为什么不用二叉树存储呢?
    我们可以看到二叉树确实有修改,但是层级过高,因为我们的索引是存储在磁盘上的。索引每次Io都需要花费时间,
如果是百万级别的数据存储,那岂不是很多次I了吗
 
 
因为二叉树的层级不受控制,且存在的问题是 单边如果过长就会出现长链表形式,这样也没有优化到哪里去
二、为什么不用平衡二叉树存储呢?
        可以看到 虽然我们在添加数据的时候 会有层级的维护,和自身的平衡,但是这都是需要花费磁盘空间的。同样平衡二叉树提高了查询的性能但是依然没有解决了层级的问题,他针对的平衡是左子树平衡右子树,却控制不了层级关系,且每个节点只有两个子节点,就成了瘦高的树,空间开销大,浪费资源 B树就是在这基础上做出的优化
三、为什么不用红黑树?
    红黑树其实和平衡二叉树差不多,只不过没有追求平衡,虽然自旋少了一些步骤,但是也浪费性能(虽然比平衡二叉树少一些自旋)和层级过高浪费磁盘IO以及节点二叉的存储结构浪费空间,平衡二叉树的缺点他都有
 
 
 
四、为什么不用B树?(Balanced Tree)
  B树很优秀,早期确实MySql用过B树作为存储,每个节点可以存储多个索引和值比起平衡二叉树单一的索引和值要好很多,但是在MySql中除了叶子节点其他节点存储的都是索引和值,但是MySql有更优秀的存储方案,B树叶子节点不是连续性的B+树是
 

 

 每个节点优化成了  区间索引 例如 【54.....76】 每个节点有16kb的空间    key小于54 走 左边的子节点树,   key=54 直接拿数据, key>76走右边的子节点树, 如果key >54 && key<76 走中间的 子节点树

 

 

 
五、MySql存储数据类型B+树
    在MySql中 数据存储的是B+树  可以看到。 B+树的特性点,叶子节点包含了后面那个节点的指针,而且是连续性的,
    在MySql中 B+树的层级控制在了,3层,而且存在多个根节点,每个除了叶子节点外的节点,存储的都是冗余索引,而不是数据本身,叶子节点存储的是索引+数据+后面叶子节点的指针,
    MySql给 每个根节点,和每个树杆节点开辟的空间大约是4kb,而每个4kb里面存储的都是冗余索引。也就是说,一次查询只需要三次IO操作  总体时间为 O(3) 大大提升了查询的效率

 

 B树和B+树的区别:

   平衡二叉树 虽然是用了树的结构,也体现了二叉查找法,但是 每个节点只能最多有两个子节点,而我们的mysql 存储是采用磁盘块来存储的,每个磁盘块的空间有16kb,使用平衡二叉树大大的浪费的存储空间,节点有限,自然会导致树很瘦很高的问题 比较瘦高的树。

   B树 优化的平衡二叉树的缺点,体现了二叉查找法,并且在平衡二叉树基础之上做出了优化,每个节点的子节点可以多多2个,这样就可以有多个子节点存储数据索引了,这样就可以减少树的层级了,也从单一索引,优化成了 区间索引,对于区间索引代表出来的 key 也会把数据一并存储在节点上,最早MySql 是使用这种存储的,但是B树也有很大的优化空间

   B+树 在B树的基础上 优化了 根节点 子节点 只存储区间索引key 和区间索引key对应多个子节点的指针,并不会存储真正的数据 也就是 16kb的磁盘块树节点 只用来存储索引和指针,大大增加了 索引的空间,数据只存储在叶子节点上,并且叶子节点与叶子节点中也会有 指针连续 按主键码从小到大链接

   B+树每个叶子节点都有一个指向相邻叶子节点的指针。数据库的查询往往会有针对范围的查找,不可避免的需要遍历整棵树或者部分子树,B+树只需要遍历叶子节点就可以遍历整棵树,查询效率要远远高于B树。

 

 

  

 
MySql事务隔离级别
    一般关系型数据库的事务隔离级别一共分为以下四种:其中mysql默认的是可重复读,Oracle默认的是读已提交
MySql在实现 可重读的同时 使用的是MVCC 快照模式,开启事务的时候会生成一个快照,而且快照是有版本号的,随后提交时就会去判断版本号是否一致,然后+1提交操作
我们测试一下 MySql的可重复读
    首先我们开启 事务1 
开启 事务2  
更新事务1 并且提交,此时我们的数据库里 id是1的age 已经是13了 
查询一下事务2,依然是12,这个时候事务2读取的是 事务刚开启时的快照
我们同样在事务2中更新 id=i的 age=12 的人,但是应该是更新不成功的,因为库里的age已经被事务1 更新过了,现在应该是13
结果是0行受影响,这就是MySql的可重复读,读取没有影响但是更新有影响,高并发下不建议使用这种操作
posted @ 2022-03-13 13:52  郎小乐  阅读(675)  评论(0)    收藏  举报