1.深入理解MySQL索引底层数据结构与算法

文章目录

索引的概念

索引是帮助MySQL高效获取数据的排好序数据结构

数据结构

网址: https://www.cs.usfca.edu/\~galles/visualization/Algorithms.html

二叉树

如果底层使用二叉树的话,比如顺序插入:1,2,3,4,5,6,7

那么数据结构就会变成一下这样

由动画可见,变成一个链表,这时候要查询6,就会经过6次查询才能找到,这个时候和全表扫描没什么区别。效率没什么提升。

红黑树

那么为什么不使用红黑树呢,当然使用红黑树也会出现问题,如果按照以上数据插入的时候,动画如下:

这时候如果要查询6的话,只需要经过三次查询,分别是2,4,6经过三次查询,和二叉树相比少了一半的查找时间,

那么为什么没有使用红黑树呢?

  • 树的高度:现在是有7条数据假设数据量是几百万行呢,所以红黑树也不是最好的选择。
  • 自旋:每次插入数据都是进行判断,是否符合红黑树规则,若不符合进行自旋,如果频繁插入就会导致频繁,浪费性能。

B-

让存储空间稍微大一点,可以放更多的数据元素(第一行数据),一个大的节点下放很多小的索引元素,data可能是索引所在行的磁盘空间,一个小的节点就是一个KV。

对比红黑树又有了提升,其实底层也不是完全使用了B-树,而是自己在B-树上进行了改造,使用了B+树。

B+

和B-树对比,将data放在了叶子节点上,那么这么做有什么好处呢:

首先是非叶子节点的大小,可以存放更多的索引数据

其次叶子节点包含了整表的数据元素。

非叶子节点是什么东西呢?

其实就是冗余索引 ,为了构建B+树。

每个节点都是排好序的,从左到右,依次递增,其实B-也是具有的。

两者的区别

  1. 指针的区别:就是B+树是存在左右箭头⬅️➡️指针的,存在下个节点的所在位置,可以快速查找。

  2. 数据量大小:

    • B+树 : 假设用Bitint做主键,每个索引占用8个字节(8B),下个文件的所在文件地址在C语言底层大概占用6B,MySQL索引大小默认是16KB,可以放置1170个元素,第二层又可以放置1170个元素,叶子节点有个date元素,可能是文件的所在地址,也可能是数据本身,这个数据就比较大,假设为1KB,那么总数据量为 1170117016 = 21902400个元素
    • B-树,假设也是三层按照以上逻辑计算为161616 = 4096个元素

    真正运行中MySQL可能会把根节点常驻内存中,这样效率得到进一步提升。

Hash

Hash的数据结构是将值进行hash之后放进哈希桶之中,比如Alice进行Hash之后是2放在2的后面,Jim进行Hash之后还是2通过链表的形式放在了Alice的后面,Tom通过hash之后得到4,放在4的后面。

如果要查询Tom可以直接进行Hash,得到4,从而直接得到数据,这种时候获取数据的形式比B+树要更高效。

但是有个弊端,就是没办法进行范围查询。

引擎

数据所在位置

对应关系

两种引擎的区别是什么呢

MyISAM

由上图可见,MyISAM引擎的数据和索引是分开来的(account)

  • frm为数据表结构相关的信息
  • MyD 数据
  • MyI 索引

底层文件分为

InnoDB

由上图可见,MyISAM引擎的数据和索引是分开来的(test_myisam)

  • frm为数据表结构相关的信息
  • idb为数据和索引

底层文件分为:

索引

主键

为什么必须包含主键?

能够唯一区分表中的每一行数据。 如果没有主键的话,更新或者删除表中的特定行就会很困难。如果没有设置主键,数据库本身就会自己帮忙维护一个虚拟主键。

为什么推荐整形自增?

首先索引是一个排好序的数据结构,其次数据库的资源性能都是比较宝贵和昂贵的,让数据库自己去排序,显而有点浪费资源。

聚集索引

由于InnoDB底层文件图片可知聚集索引的叶子节点存的是数据,找到之后可以直接把数据取出来。不涉及到回表的操作,在性能上高于非聚集索引。

非聚集索引

为什么建立二级索引?假设一张表的数据比较多,我多建几个索引很正常吧!

由于InnoDB底层文件图片可知聚集索引的叶子节点存的是一级索引的key,这个时候设计到一个回表查询的一个操作。

这也是为什么引擎逐渐改为了InnoDB引擎的原因,MyISAM通过索引查询数据涉及到了跨文件查询。

为什么非聚集索引存的是聚集索引的key(主键值)

  • 第一是为了节省空间,假设也是存数据到话,data可能会很大,占用太多的资源空间
  • 第二是为了保证一致性,假设要插入一条数据,主键写入成功后,二级索引也要写入成功算是成功,如果写入主键值会快很多并且出错率更低。

联合索引

遵循最左前缀原则,那么为什么要遵循最左原则呢?

假设一:遵循最左原则:查询name 和 age

条件为:Bill和30

可以得到第一条数据

假设二:不遵循最左原则:查询age和position

条件为:30和dev

查询到了第一条数据,这个时候后面还有符合的数据就需要重新回表查询

因为索引是排好序的数据结构

如有写的不对的请指正。

相关推荐
云和数据.ChenGuang21 分钟前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
woshilys1 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver
Hacker_LaoYi1 小时前
SQL注入的那些面试题总结
数据库·sql
建投数据2 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
Hacker_LaoYi3 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀3 小时前
Redis梳理
数据库·redis·缓存
独行soc3 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
你的微笑,乱了夏天3 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺4 小时前
分布式系统架构:服务容错
数据库·架构
独行soc5 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘