当前位置: 首页 > news >正文

Mysql 学习day 2 深入理解Mysql索引底层数据结构

深入理解Mysql索引底层数据结构

    • 简介
    • 可用的数据结构
    • myisam和innoDB
      • 对于 MyISAM 存储引擎:
      • 对于 InnoDB 存储引擎:
      • 例子
    • 联合索引的底层存储结构长什么样?

简介

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

索引是MySQL中用于快速定位和访问数据的一种机制。它通过特定的数据结构(如B+树)对数据进行组织和排序,帮助数据库引擎快速找到所需数据行,从而减少查询时间。索引并不存储完整数据,而是存储指向数据的引用或键值。在查询过程中,索引可以缩小扫描范围、支持排序等功能,显著提升数据库的查询效率。常见的索引类型包括普通索引、唯一索引、主键索引和全文索引等。

一行行查找,放磁盘,但是放进磁盘的顺序是混乱的
索引key放值,value放地址

可以用可视化图做例子

可用的数据结构

为什么数据结构不用二叉树,因为二叉树插入变成了链表,查找次数多,对查找效率没有提升
可以看这个链接,更详细
在这里插入图片描述
为什么不用红黑树
红黑树是平衡二叉树
因为数据量大的时候,红黑树层数会增多,查找效率会降低,高度不可控
在这里插入图片描述

为什么不用b树
1.叶节点具有相同的深度,叶节点的指针为空
2.所有索引元素不重复
3.节点中的数据索引从左到右递增排列

在这里插入图片描述

为什么用B+树
在这里插入图片描述
B+Tree(B-Tree变种)

  1. 非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
    MySQL的B+树中,非叶子节点存储的是键值范围的划分点,这些键值是从叶子节点中抽样出来的,用于快速引导查询路径,帮助构建树的层级结构,从而加速数据定位。这些划分点并不是实际存储的数据,而是中间引索,目的是指导查询快速找到目标数据所在的叶子节点。
  2. 叶子节点包含所有索引字段
  3. 叶子节点相邻之间用指针连接,最前端或者最尾端开辟了内存存储上一个和下一个的地址,提高区间访问的性能
    第二层其实是冗余节点

三层可以存多少数据

myisam和innoDB

myisam和innoDB区别

在 MySQL 中,数据的存储方式取决于所使用的存储引擎,因为不同的存储引擎具有不同的数据存储和管理机制。以下以两种最常用的存储引擎——MyISAMInnoDB——为例,介绍数据在多个列情况下的存储方式。

对于 MyISAM 存储引擎:

  • 表结构存储:每个 MyISAM 表由三个文件组成,分别是 .frm 文件(存储表定义或表结构)、.MYD 文件(存储数据)和 .MYI 文件(存储索引)。
  • 数据行存储:数据行中的各列数据按照列的定义顺序依次存储在 .MYD 文件中。对于每个数据行,其存储顺序是固定的,且每列数据紧密排列。例如,若表中有多个列(如 idnameage 等),那么每行数据在 .MYD 文件中会按 idnameage 的顺序依次存储对应的数据值。
  • 索引存储:索引存储在 .MYI 文件中,每个索引包含键值以及指向数据行的指针。当通过索引查找数据时,MySQL 会先在索引文件中找到对应的键值,然后通过指针定位到 .MYD 文件中相应的数据行位置。

对于 InnoDB 存储引擎:

  • 表空间存储:InnoDB 使用表空间来存储数据,默认情况下所有 InnoDB 表的数据都存储在一个系统表空间中(由 ibdata1 文件等组成)。从 MySQL 5.7 开始,也支持将每个表的数据独立存储在单独的表空间文件(以 .ibd 为后缀)中。
  • 聚集索引(聚簇索引):InnoDB 表中的数据行是按照主键(primary key)顺序存储的,这种索引被称为聚集索引。数据行与主键索引结合在一起,主键索引的叶子节点直接存储了完整的数据行。如果表中没有显式定义主键,InnoDB 会自动选择第一个非空的唯一列作为主键,若没有这样的列,则会自动生成一个隐藏的主键。
  • 二级索引:对于非主键的索引(二级索引),其叶子节点存储的是主键值,而不是完整的数据行。当通过二级索引查找数据时,MySQL 先从二级索引中找到对应的主键值,然后再通过主键值在聚集索引中定位到完整的数据行。
  • 行溢出存储:如果某列的值很大(如长的变长字符串列),为了保证聚集索引的效率,InnoDB 可能不会将整个列的值存储在聚集索引的页中,而是存储一个指针,该指针指向存储在其他位置的完整列值(行溢出存储)。

总的来说,MySQL 的数据存储方式因存储引擎而异,MyISAM 引擎将数据和索引分开存储,数据按列顺序排列;而 InnoDB 引擎采用聚集索引的方式组织数据,并且二级索引与数据行通过主键关联。这些存储方式对于数据库的性能和数据管理都有重要影响。

索引是存在磁盘上的data目录下面

在这里插入图片描述

例子

一个test表
用的myisam存储引擎,frm文件存放着是表结构信息,myd文件存放着是myisam表的记录,myi文件就是index表
myI里面得到索引记录,然后去myd文件里面得到数据,可以看做是非聚簇索引

InnoDB存储引擎的IBD文件就是所有数据放进去

InnoDB索引实现(聚集)

  1. 表数据文件本身就是按B+Tree组织的一个索引结构文件

  2. 聚集索引-叶节点包含了完整的数据记录

  3. 为什么建议InnoDB表必须建主键?
    因为如果不建主键,他就会找从第一列选择一列索引建立和维护B+树
    如果选不到索引,会建立rowid隐藏列来组织B+树

  4. 为什么推荐使用整型的自增主键
    因为整型比大小快,一般企业用固态硬盘,节约空间

什么是自增?
假设列设为哈希索引,对索引进行哈希,然后插入,mysql底层有自己的hash算法,另外一个需要自增的原因,如果是乱序插入,树会变成乱序,会分裂新的节点

	Hash1. 对索引的key进行一次hash计算就可以定位出数据存储的位置2. 很多时候Hash索引要比B+ 树索引更高效3. 仅能满足 “=”,“IN”,不支持范围查询,B+树范围查找是把一个范围的数据页都load出来4. hash冲突问题

在这里插入图片描述
工作中,一般不用哈希,比如果name>Alice,就需要全表扫描,所以一般是b+树

  1. 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
    因为如果都放所有数据,如果有修改的时候两个表都需要修改数据,如果是其中一个放的是主键值,在MySQL中,利用主键值在聚集索引(主表)中查找完整数据行的过程如下:首先,通过主键值在B+树结构的聚集索引中逐层查找,直到定位到存储完整数据行的叶子节点。若数据所在的页未在内存中,则从磁盘加载该页到内存。最后,在内存中的数据页里找到对应的行并返回结果。整个过程通常只需一次I/O操作(若数据页已加载则无需I/O),效率较高,但回表操作的瓶颈可能在于磁盘I/O和数据页加载次数。

联合索引的底层存储结构长什么样?

在这里插入图片描述
如果不匹配最左侧原理,就会扫描所有表

联合索引可以使用的脚本

CREATE TABLE `employees` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',`position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',`hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',PRIMARY KEY (`id`),KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='员工记录表';INSERT INTO employees(name,age,position,hire_time) VALUES('LiLei',22,'manager',NOW());
INSERT INTO employees(name,age,position,hire_time) VALUES('HanMeimei', 23,'dev',NOW());
INSERT INTO employees(name,age,position,hire_time) VALUES('Lucy',23,'dev',NOW());EXPLAIN SELECT * FROM employees WHERE name = 'Bill' and age = 31;
EXPLAIN SELECT * FROM employees WHERE age = 30 AND position = 'dev';
EXPLAIN SELECT * FROM employees WHERE position = 'manager';

关于最左前缀的补充
MySQL一定是遵循最左前缀匹配的,这句话在mysql8以前是正确的,没有任何毛病。但是在MySQL 8.0中,就不一定了。
索引跳跃扫描(Index Skip Scan)
参考:https://dev.mysql.com/doc/refman/8.0/en/range-optimization.html#range-access-skip-scan

官网示例
CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2));
INSERT INTO t1 VALUES
(1,1), (1,2), (1,3), (1,4), (1,5),
(2,1), (2,2), (2,3), (2,4), (2,5);
INSERT INTO t1 SELECT f1, f2 + 5 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 10 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 20 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 40 FROM t1;
ANALYZE TABLE t1;EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40;
这里f1和f2是联合索引

在这里插入图片描述

虽然我们的SQL中,没有遵循最左前缀原则,只使用了f2作为查询条件,但是经过MySQL 8.0的优化以后,还是通过索引跳跃扫描的方式用到了索引了。

索引跳跃扫描优化原理
mysql8.013后通过优化器帮我们加了联合索引,SQL执行过程如下:
1.获取 f1 字段第一个唯一值,也就是 f1 = 1
2.构造 f1 = 1 and f2 > 40,进行范围查询
3.获取 f1 字段第二个唯一值,也就是 f1 = 2
4.构造 f1 = 2 and f2 > 40,进行范围查询
SELECT f1, f2 FROM t1 WHERE f2 > 40;

执行的最终SQL:
SELECT f1, f2 FROM t1 WHERE f1 =1 and f2 > 40
UNION
SELECT f1, f2 FROM t1 WHERE f1 =2 and f2 > 40;

所以对于对于f1值很少,区分度不高的情况索引跳跃扫描会快一些;反之查询效率慢些。
我们不能依赖这个优化,建立索引的时候,还是优先把区分度高的,查询频繁的字段放到联合索引的左边。

限制条件

  • 查询必须只能依赖一张表,不能多表JOIN。
  • 查询中不能使用 GROUP BY 或 DISTINCT 语句。
  • 查询的字段必须是索引中的列。
  • 组合索引形式:([A_1, …, A_k,] B_1, …, B_m, C [, D_1, …, D_n]),A,D 可以为空,但是B ,C 不能为空。
http://www.dtcms.com/a/359135.html

相关文章:

  • 【开题答辩全过程】以 基于WEB的茶文化科普系统的设计与实现为例,包含答辩的问题和答案
  • 用简单仿真链路产生 WiFi CSI(不依赖专用工具箱,matlab实现)
  • 面试tips--MyBatis--<where> where 1=1 的区别
  • 如何查看Linux系统中文件夹或文件的大小
  • 【LeetCode - 每日1题】有效的数独
  • SQLSugar 快速入门:从基础到实战查询与使用指南
  • MySQL 在 CentOS 上的安装与配置文件路径详解
  • 【系列06】端侧AI:构建与部署高效的本地化AI模型 第5章:模型剪枝(Pruning)
  • 【LeetCode - 每日1题】鲜花游戏
  • 深度学习:洞察发展趋势,展望未来蓝图
  • Verilog 硬件描述语言自学——重温数电之典型组合逻辑电路
  • 深度学习通用流程
  • 用更少的数据识别更多情绪:低资源语言中的语音情绪识别新方法
  • nestjs连接oracle
  • 大模型备案、算法备案补贴政策汇总【广东地区】
  • SNMPv3开发--snmptrapd
  • CNB远程部署和EdgeOne Pages
  • More Effective C++ 条款18:分期摊还预期的计算成本(Amortize the Cost of Expected Computations)
  • 数据库的CURD
  • Shell 秘典(卷三)——循环运转玄章 与 case 分脉断诀精要
  • C语言类型转换踩坑解决过程
  • Java高并发架构核心技术有哪些?
  • 安装Redis
  • compute:古老的计算之道
  • 【ROS2】ROS2 基础学习教程 、movelt学习
  • Docker实战避坑指南:从入门到精通
  • plantsimulation知识点 多条RGV驮一台工件图标显示顺序问题
  • lumerical_FDTD_光源_TFSF
  • 【AI】【强化学习】强化学习算法总结、资料汇总、个人理解
  • php连接rabbitmq例子