十四、深入理解Mysql索引底层数据结构与算法

news/2024/10/7 14:08:34/

文章目录

  • 一、索引的本质
    • 1、索引是帮助MySQL高效获取数据的排好序的数据结构
    • 2、索引的数据结构
    • 3、数据结构可视化网站
  • 二、常见数据结构介绍
    • 1、B-Tree
    • 2、B+Tree(B-Tree变种)
    • 3、Hash结构
  • 三、存储引擎的索引实现
    • 1、MyISAM存储引擎索引实现
      • MyISAM索引文件和数据文件是分离的(非聚集)。
    • 2、InnoDB存储引擎索引实现
      • InnoDB索引实现(聚集):
  • 四、联合索引
    • 1、联合索引案例使用的脚本
    • 2、索引最左前缀原理
    • 3、关于最左前缀的补充
      • 索引跳跃扫描(Index Skip Scan)
      • 索引跳跃扫描优化原理
      • 生效的限制条件

一、索引的本质

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

在这里插入图片描述

2、索引的数据结构

  • 二叉树
  • B-Tree
  • Hash表
  • 红黑树

3、数据结构可视化网站

为了更好的了解数据结构,直观的感受数据结构的变化,可以使用如下网站,进行可视化操作。
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

二、常见数据结构介绍

1、B-Tree

  • 叶节点具有相同的深度,叶节点的指针为空。
  • 所有索引元素不重复。
  • 节点中的数据索引从左到右递增排列。
    在这里插入图片描述

2、B+Tree(B-Tree变种)

  • 非叶子节点不存储data,只存储索引(冗余),可以放更多的索引。
  • 叶子节点包含所有索引字段。
  • 叶子节点用指针连接,提高区间访问的性能。
    在这里插入图片描述

3、Hash结构

  • 对索引的key进行一次hash计算就可以定位出数据存储的位置。
  • 很多时候Hash索引要比B+ 树索引更高效。
  • 仅能满足 “=”,“IN”,不支持范围查询。
  • hash冲突问题。
    在这里插入图片描述

三、存储引擎的索引实现

1、MyISAM存储引擎索引实现

MyISAM索引文件和数据文件是分离的(非聚集)。

在这里插入图片描述

2、InnoDB存储引擎索引实现

InnoDB索引实现(聚集):

  • 表数据文件本身就是按B+Tree组织的一个索引结构文件
  • 聚集索引-叶节点包含了完整的数据记录
  • 为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?(方便排序提升查找效率)
  • 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)

四、联合索引

1、联合索引案例使用的脚本

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';

2、索引最左前缀原理

在联合索引中,索引的数据结构如下,正常的索引是遵循B+树结构,索引项从左到右,从小到大排序,假设我们跳过name,直接使用联合索引中的ageposition,由于在比较中,无法先确认第一项name,故无法对整个索引项进行排序,从而导致联合索引失效。
简单理解,其实索引的最左前缀原理就是根据索引中开始的索引字段,按顺序进行匹配排序,实现通过索引的高效查找的的一种规则。
在这里插入图片描述

3、关于最左前缀的补充

索引跳跃扫描(Index Skip Scan)

MySQL一定是遵循最左前缀匹配的,这句话在mysql8以前是正确的,没有任何毛病。但是在MySQL 8.0中,就不一定了。

参考: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;

在这里插入图片描述
虽然我们的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.ppmy.cn/news/1535724.html

相关文章

Node.js env 环境变量多种配置方式

目录 process.env 配置方式 dotenv 使用 cross-env process.env 在 Node.js 中,你可以使用 process.env 对象来读取环境变量。这个对象包含了所有的环境变量,你可以通过变量名来访问这些变量的值。 例如,如果你有一个名为 MY_VARIABLE …

Element UI教程:如何将Radio单选框的圆框改为方框

大家好,今天给大家带来一篇关于Element UI的使用技巧。在项目中,我们经常会用到Radio单选框组件,默认情况下,Radio单选框的样式是圆框。但有时候,为了满足设计需求,我们需要将圆框改为方框,如下…

03.useToggler

在 React 应用中,切换布尔状态是一个常见的需求,比如开关按钮、显示/隐藏元素等。useToggler 钩子提供了一种简洁而高效的方式来管理这种二元状态。这个自定义钩子不仅简化了代码,还提高了组件的可读性和可维护性。以下是如何实现和使用这个自定义钩子: const useToggler …

佑航科技Pre-A+轮融资成功:加速车载超声波芯片研发与量产

近日,超声波芯片领域的领先企业珠海佑航科技有限公司(简称“佑航科技”)宣布成功完成数千万元的Pre-A+轮战略融资。本轮融资由上市公司思瑞浦微电子旗下的芯阳基金进行战略投资,标志着佑航科技在车载超声波芯片及传感器领域的研发与量产能力迈上了新台阶。此次融资不仅为佑…

python并发编程实战

python并发编程有三种 多线程Thread多进程Process多协程Coroutine cpu密集型计算 cpu密集型也叫计算密集型,是指I/O在很短的时间就可以完成,cpu需要大量的计算处理,特点是cpu占用率相当高 例如:压缩解压缩、加密解密、正则表达…

Web3 游戏周报(9.22 - 9.28)

回顾上周的区块链游戏概况,查看 Footprint Analytics 与 ABGA 最新发布的数据报告。 【9.22-9.28】Web3 游戏行业动态: Axie Infinity 将 Fortune Slips 的冷却时间缩短至 24 小时,从而提高玩家的收入。 Web3 游戏开发商 Darkbright Studios…

音频搜索公司 DeepGram,定位语音搜索AI大脑,DeepGram想做“音频版”

1. 亦仁分享 DeepGram 成立于 2015 年,位于美国山景城,是一家基于 AI 技术的音频搜索引擎公司。运用机器学习进行语音识别、搜寻重要时刻并对音频和视频进行分类,帮助用户快速索引和浏览音频和视频文件,包括电话语音、会议语音、…

数据分析之Spark框架介绍

文章目录 概述一、发展历程与背景二、核心特点三、生态系统与组件四、应用场景五、与其他大数据技术的比较 核心概念1. 弹性分布式数据集(RDD, Resilient Distributed Dataset)2. 转换(Transformations)和动作(Actions…