MySQL索引

数据表如何用索引快速查找

索引是 排好序的快速查找的数据结构

索引存储在文件系统中

索引的文件存储形式与存储引擎有关

索引数据结构:可以是二叉树、红黑树、Hash表、B-Tree、B+Tree

1、二叉树

使用索引的如下图:(如果是使用二叉树结构每一个节点都存放数据行的磁盘地址【快速定位到数据】

虽然索引不是使用的二叉树,而是使用B+Tree结构,为什么不使用二叉树呢?

如果索引是连续的数字,二叉树就会蜕变成链表,访问的速度还是和没加索引一样

这时再查找效率就变低了

2、红黑树

红黑树作为索引的数据结构呢,其实红黑树是二叉平衡树,到某个节点数值的绝对值超过2,就会重新排列(该节点不平衡),但是为什么索引还没 有选择红黑树呢,原因是树的高度比较高(一直是二叉),索引树的高度比较高,和磁盘进行IO操作比较多

3、BTree

BTree又叫多路平衡搜索树,就是一个节点开辟更大的空间,(横向)存放多个索引

  • 叶子节点具有相同的深度,叶子节点的指针为空
  • 节点中的数据从左到右递增排列

这样树的高度就解决了,横向存储更多,但是为什么不选择BTree呢,因为页节点有默认大小的,如果每个节点都存储数据data,这时页节点就存储的个数不多,这样会增加树的高度.

4、B+Tree

B+Tree对BTree做了点优化,非叶子节点不存data数据,一个节点MySQL底层叫做页节点(默认分配16KB大小)

SHOW GLOBAL STATUS like 'Innodb_page_size';

索引一般使用int 默认是8B,指针是存储下一个页节点的地址大小为6B,所以一个页节点可以存放 16KB /(6+8)B = 1170 个 高度为3 的可以存放 = 1170 * 1170 * 16 差不多两千万多

5、MyISAM存储引擎实现

MyISAM不支持事务、也不支持外键,其优势是访问的速度快,对事务的完整性没有要求

创建一个存储引擎是MyISAM的test_MyISAM表

【注意】

MySQL8开始删除了原来的frm文件,并采用 Serialized Dictionary Information (SDI), 是MySQL8.0重新设计数据词典后引入的新产物

myIsam.MYD:存储表的数据信息

myIsam.MYI:存储表的索引信息(index)

从上面的索引中可以看到,通过索引查找数据最后是定位到物理地址(MYD文件)所在的位置

比如通过where条件查询时,会判断是不是索引,如果是索引,每次查找时,把当前的页子节点从磁盘中(.MYI文件)加载到内存中【这是一个比较耗时的操作,该操作也是一次IO操作】,这也是典型的非聚集索引(索引文件和数据文件分离的

6、InnoDB存储引擎实现

InnoDB存储引擎是MySQL默认存储引擎,InnoDB存储引擎提供了具有提交、回滚、崩溃恢复能得事务安全

聚集索引:数据和索引存放在一起

InnoDB存储引擎的表必须建立主键,建立了主键,主键就是聚集索引

聚集索引查找数据的图结构如下:

创建以InnoDB存储引擎的表test_InnoDB,查看表结构

在MySQL8就只有一个.ibd文件,之前的版本是有.frm文件的

数据和索引都存放在.ibd文件中,就如上图一样,主键索引(聚集索引)自带完整的数据,普通的索引是自带id主键,再通过id主键获取数据data

如图:先定位id主键值,再回表查询(通过id值查询–》聚集索引

1)为什么建议InnoDB表必须建立主键,并且推荐使用整型自增主键?

如果不建立主键,数据库会找一个唯一区别的列作为主键,如果没找到就增加一个隐藏列rowid来维护索引(使用B+Tree),我们尽量节省MySQL的性能,不要它帮我们建立。

推荐使用整型的自增主键,因为如果使用字符串查询时是逐位比较每一位字符,比较慢

2)为什么非主键索引结构叶子节点存储的是主键值?

  • 保持一致性

当数据库表进行DML操作时,同一行记录的页地址会发生改变,因此非主键索引保存的是主键值,无需要进行改变

  • 节省存储空间

InnoDB数据本身就是汇聚到主键索引所在的B+Tree上了,如果普通索引还继续再保存一份数据,就会出现有多少索引就会存多少份数据

7、Hash表

索引也是可以设定位Hash表,但是使用不多

对索引的key进行hash计算确定数据存储的位置(数组下标位置),如果出现hash冲突时,通过链地址法解决冲突

  • Hash索引无法被用来避免数据的排序操作

由于Hash索引中存放的是经过Hash计算之后的Hash值,而且Hash值的大小关系并不一定和Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;

  • 但是Hash索引仅能满足 “=” ,“in” ,不支持范围查询

由于Hash索引比较的是进行Hash运算之后的Hash值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样。

  • 还有Hash冲突问题,如果冲突很多维护代价很高

  • Hash索引不能利用部分索引键查询

对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值,而不是单独计算Hash值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash索引也无法被利用

  • Hash索引在任何时候都不能避免表扫描

Hash索引是将索引键通过Hash运算之后,将 Hash运算结果的Hash值和所对应的行指针信息存放于一个Hash表中,由于不同索引键存在相同Hash值,所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果

  • Hash索引遇到大量Hash值相等的情况后性能并不一定就会比BTree索引高

如果创建Hash索引,那么将会存在大量记录指针信息存于同一个Hash值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。

上面的两点算是不选择Hash索引的原因

通过Hash索引怎么查找数据呢???

比如使用Hash索引时,查找数据,首先计算hash值,再到链表查询数值,在定位到物理地址,才算是查找成功

哈希碰撞很多时,查询还是会变的缓慢,因为必须要遍历链表中对应的所有数据行进行匹配,同样更新索引的效率也会受到影响,导致数据的新增、修改、删除速度变慢。

既然Hash索引是不支持范围查找,那么B+Tree是怎么范围查询的呢??

8、B+Tree的范围查找

叶子节点用指针连接,提高区间访问的性能

比如查找 范围在20-50的数据,首先查找20,之后通过20后面的指针指向后面的往后查找,直到查找到大于50的为止(通过这个叶子节点的指针可以看出,连续且自增的主键好处),使用主键自增的可以避免页节点的元素分裂导致范围查询效率低

复合索引的最左前缀优化原则

对于复合索引,它的索引B+Tree是怎么样构建的呢?

联合索引首先按照第一个字段排序,如果第一个相同再按照第二个字段排序,依次类推

9、索引分类

1、主键索引
2、唯一索引
3、普通索引(辅助索引 或者 二级索引)
4、全文索引
5、组合索引
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值