Mysql性能优化- B+tree索引

为什么要用索引?
索引能够极大的减少存储引擎需要扫描的数据量
索引会可以把随机io 变成顺序io
索引可以帮助我们在进行分组排序等操作时避免使用临时表
索引是什么?
索引是位了加速对表中数据进行检索而创建的一种分散存储的数据结构
能够提高查询性能的数据结构有什么?

二叉树
作用:通过二分查找缩小数据查找的范围 提高效率
在这里插入图片描述
不足:当数据不规则的时候容易出现 不平衡的情况趋近于链表 导致效率下降
在这里插入图片描述
平衡二叉树:

完全平衡二叉树 avl Tree 节点子节点高度差不能大于1
相对平衡二叉树
在这里插入图片描述
在做数据插入时会为了保证数据平衡而做一些操作,每次插入后都重构原有数据结构使数据结构高度差不大。
解决了二叉树不平衡的问题
依然存在的问题:
1、太深了- 节点的深度决定了数据io的次数
比如上图要检索出 8 要做 3次io操作。读写三次磁盘 如果更深的节点需要的io次数更多。对于百万级甚至更多数据时io次数会很多。效率会降低
2 、太小了- 一次io只读取一个节点的数据 每次加载数据量少就会导致io次数多
没有很好利用操作系统和磁盘的数据交换特性(计算机和硬盘io以页为单位,每页大小4k ),一个节点的数据显然不够一页。如果一次io能多拿一些数据,效率肯定会提高
没有利用磁盘IO的预读能力从而频繁io ,在io交换的时候硬盘认为度了这4k 会马上要读下一个4k 可能会一并加载 ,从而减少io次数

B-Tree 多路平衡查找树

路:就是最多子节点数 二叉树就是二路树 下图为三路查找树
关键字:关键字个数为路数-1 所以最多有两个关键字
在这里插入图片描述
增加将每个节点路数使节点的数据量达到4K ,比如有512路。那么树的深度大大降低。而且每次读取的数据量够大 还利用了磁盘io预读等特性 从而大大增加检索效率。

B+Tree 加强版 多路平衡查找树

1、采用闭合区间 路数和关键字数相同。
2、分支节点不保存任何信息,所有信息都保存在叶子节点。 分支节点没有数据区 只有关键字和子节点索引
3、叶子节点是顺序排列的 并且相邻节点具有顺序引用的关系 即叶子节点是线性链表

在这里插入图片描述
优点:
是Btree的加强版 具有bTree 的优势
扫库表能力更强 btree 有数据区 每次读取的关键词数量 没有b+tree 多 而且b+tree 路数也越多
磁盘读写能力更强 b 有数据区 所以浪费磁盘空间 每次读取的关键词数量 没有b+tree 多。
排序能力更强 叶子节点是线性链表
查询效率更稳定(仁者见仁智者见智) 因为不分支节点不保存数据信息所以每次都要查询到叶子节点。而Btree 分支节点也保存数据信息所以 可能两次就能返回也可能 n次返回。相对来说B+tree稳定。

结论

1、索引不宜建多 会影响插入或更新删除的性能。原因:增删改时需要维护索引树的规则。

这也是为什么很多时候使用逻辑删除。减少索引树的维护。增加效率

Mysql索引在库种表现

Innodb 引擎

该引擎创建的表包含 两个文件
*.frm 表定义文件
*.ibd 表数据文件
索引信息也保存在数据文件中。以主键为索引来组织数据的存储 —聚集索引

在这里插入图片描述
两个索引的情况
主键索引为聚集索引 其他索引为辅助索引。其他索引叶子节点中保存的是主键的值。而不是直接存储数据引用。只能先找到主键再到主键索引中去找数据引用。因为该引擎认为主要会通过主键来查询数据
在这里插入图片描述
myisam引擎
该引擎创建的表包含 三个文件

  • .frm 定义文件
  • .MYD 数据文件
    • .MYI 索引文件
      索引体现形式 索引和数据分别在两个文件。 *.MYI 中叶子节点保存了该条记录的引用地址。
      在这里插入图片描述
      两个索引的情况。 id索引和name索引 都保存在索引文件中并且每个索引的叶子节点中保存了数据的引用
      在这里插入图片描述
      两种引擎对比

在这里插入图片描述

花絮:
列的离散性:count(distinct col):count(col) 比例越高离散型越好
三列的离散性:name 9/9=1 sex 2/9
在这里插入图片描述
离散性不好的列建索引如下:当要找的值为0001时选择很多,选择性很差,io次数很多效率减低
在这里插入图片描述
最左匹配原则
在这里插入图片描述

根据创建数据库时选择的字符集,和排序规则
每个索引关键字会转换成asc码等进行对比

为什么like ‘%33%’ 使用不到索引?
因为左侧匹配无法匹配选择性很差 不如做全表扫面 ‘33%’ 就可能(但不一定)用到索引。

联合索引
在这里插入图片描述
下例中name 索引没有必要,根据最左匹配原则联合索引已经包含name索引 name索引为冗余索引没必要创建
在这里插入图片描述
覆盖索引:

覆盖索引就是为什么不建议查询的时候使用 select * * 如果指定字段的话可能就直接从关键字中返回 而没有必要去访问索引的叶子节点和数据文件引用。但是如果使用*就必须去找表数据引用 显然前者效率更高
下列语句中 第二条 由于使用了主键索引 所以不会从关键字中返回 字段信息。不会使用覆盖索引。第一条查询语句可以
在这里插入图片描述
举一反三
在这里插入图片描述
1 增加路数和每次读取关键字数量 io能力就更强
2.多了会增加增删改的效率
3.
4、选择性差 不如全表扫描 in 和 like‘111%’ 都是半勾
5.
6.可能会使用覆盖索引
7.
8

Like ‘1232%’ 有时候能用个索引有时候不能用 什么时候能用什么时候不能用?
如下实例:
以下sql 没能使用索引
在这里插入图片描述
以下sql使用了索引
在这里插入图片描述
原因 :执行sql时 sql优化器根据sql判断 第一个sql的条件选择性差,就是说可以过滤出很多的关键字,比如走全表扫描 而第二个sql选择性好,可以直接使用索引
表中数据如下,gupao1可以过滤出很多数据 过滤性差
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhangxm_qz/article/details/87972592