MySQL 中的索引

news2024/11/24 19:41:41

文章目录

  • 一、索引的创建
  • 二、聚簇索引与非聚簇索引
  • 三、B+ 树索引

在这里插入图片描述


一、索引的创建

创建索引的方式包括两种:

  • 隐式创建:数据库一般会在创建 PRIMARY KEYUNIQUE 约束列时自动创建索引。
  • 显示创建:使用 CREAT INDEX 语句创建,建立之后由数据库负责使用和维护索引。

下面展示了 MySQL 中隐式创建的索引和显示创建的索引,不过需要注意的是索引查询时显示的索引类型为 BTREE,但实际上 MySQL 默认使用的是 B+ 树。

DROP TABLE IF EXISTS student;

CREATE TABLE student
(
    student_id   INT PRIMARY KEY,
    student_name VARCHAR(50) UNIQUE,
    gender       ENUM ('Male', 'Female') DEFAULT 'Male',
    major        VARCHAR(50) NOT NULL,
    birthdate    DATE        NOT NULL
);

INSERT INTO student (student_id, student_name, gender, major, birthdate)
VALUES (1, 'Alice', 'Female', 'Computer Science', '2000-05-15'),
       (2, 'Andrew', 'Male', 'Engineering', '1999-09-20'),
       (3, 'Maria', 'Female', 'Mathematics', '2001-03-10'),
       (4, 'Samantha', 'Female', 'Physics', '2002-01-25'),
       (5, 'Michael', 'Male', 'Biology', '1998-11-05'),
       (6, 'Jessica', 'Female', 'History', '1997-06-30'),
       (7, 'William', 'Male', 'Geology', '1996-04-15'),
       (8, 'John', 'Male', 'Computer Science', '1995-08-08');

SHOW INDEXES FROM student;
# +-------+----------+------------+------------+------------+---------+-----------+--------+------+----+----------+-------+-------------+-------+----------+
# |Table  |Non_unique|Key_name    |Seq_in_index|Column_name |Collation|Cardinality|Sub_part|Packed|Null|Index_type|Comment|Index_comment|Visible|Expression|
# +-------+----------+------------+------------+------------+---------+-----------+--------+------+----+----------+-------+-------------+-------+----------+
# |student|0         |PRIMARY     |1           |student_id  |A        |4          |null    |null  |    |BTREE     |       |             |YES    |null      |
# |student|0         |student_name|1           |student_name|A        |4          |null    |null  |YES |BTREE     |       |             |YES    |null      |
# +-------+----------+------------+------------+------------+---------+-----------+--------+------+----+----------+-------+-------------+-------+----------+

# 在 birthdate 字段上创建唯一索引
CREATE UNIQUE INDEX idx_major ON student (birthdate);

# 在 birthdate 字段上创建普通索引
CREATE INDEX idx_birthdate ON student (birthdate);
# +-------+----------+-------------+------------+------------+---------+-----------+--------+------+----+----------+-------+-------------+-------+----------+
# |Table  |Non_unique|Key_name     |Seq_in_index|Column_name |Collation|Cardinality|Sub_part|Packed|Null|Index_type|Comment|Index_comment|Visible|Expression|
# +-------+----------+-------------+------------+------------+---------+-----------+--------+------+----+----------+-------+-------------+-------+----------+
# |student|0         |PRIMARY      |1           |student_id  |A        |4          |null    |null  |    |BTREE     |       |             |YES    |null      |
# |student|0         |idx_major    |1           |birthdate   |A        |8          |null    |null  |    |BTREE     |       |             |YES    |null      |
# |student|0         |student_name |1           |student_name|A        |4          |null    |null  |YES |BTREE     |       |             |YES    |null      |
# |student|1         |idx_birthdate|1           |birthdate   |A        |8          |null    |null  |    |BTREE     |       |             |YES    |null      |
# +-------+----------+-------------+------------+------------+---------+-----------+--------+------+----+----------+-------+-------------+-------+----------+

SHOW TABLE STATUS LIKE 'student';
# +-------+------+-------+----------+----+--------------+-----------+---------------+------------+---------+--------------+-------------------+-------------------+----------+------------------+--------+--------------+-------+
# |Name   |Engine|Version|Row_format|Rows|Avg_row_length|Data_length|Max_data_length|Index_length|Data_free|Auto_increment|Create_time        |Update_time        |Check_time|Collation         |Checksum|Create_options|Comment|
# +-------+------+-------+----------+----+--------------+-----------+---------------+------------+---------+--------------+-------------------+-------------------+----------+------------------+--------+--------------+-------+
# |student|InnoDB|10     |Dynamic   |8   |2048          |16384      |0              |16384       |0        |null          |2023-09-24 21:09:40|2023-09-24 21:09:04|null      |utf8mb4_0900_ai_ci|null    |              |       |
# +-------+------+-------+----------+----+--------------+-----------+---------------+------------+---------+--------------+-------------------+-------------------+----------+------------------+--------+--------------+-------+

二、聚簇索引与非聚簇索引

聚簇索引:聚簇索引(clustered index)也叫聚集索引、聚类索引,一张表有且仅有一个聚簇索引。

默认情况下,MySQL 在建表时会根据不同的场景选择不同的列建立聚簇索引:

  • 聚簇索引默认是主键索引,会在定义主键时自动创建聚簇索引。
  • 如果表中没定义主键,那么就选取首个非空且唯一的索引列来建立聚簇索引。
  • 如果前两条都不满足,那么数据库就创建一个隐藏的 row-id 作为聚簇索引。

对于一个主键聚簇索引来说,叶子结点中按照主键顺序依次存放着整张表的全部记录。这个特性决定了索引组织表中的数据本身就是索引的一部分,每张表也只能拥有一个聚簇索引。


非聚簇索引:非聚簇索引(secondary index)也叫辅助索引、二级索引,一张表可以有多个非聚簇索引。

辅助索引不是建立在记录上的,而是建立在上述的聚簇索引上的。对于一个非聚簇索引,叶子结点中只存放当前关键字以及对应的聚簇索引关键字(见下例),当我们要查找整条记录时,需要在访问非聚簇索引的叶结点后继续访问聚簇索引查找完整信息,这个过程也叫做回表,总计需要查找两次索引。


基于上面示例中的 student 表,如果 student_id 聚簇索引采用 B+ 树来实现,那么这个聚簇索引的四个叶子结点中会按 student_id 递增依次存放对应记录。当我们通过 student_id 聚簇索引查询住址时,会直接在叶子结点中查找成功。如果我们再在 studnet_name 字段上建立一个非聚簇索引,叶子结点只会存放 studnet_namestudent_id ,不会存储完整记录。当我们通过 studnet_name 非聚簇索引查询住址时,在非聚簇索引中根据 studnet_name 查找到 student_id 后,要继续根据 student_id 回表查找地址。

s t u d e n t _ i d (主键聚簇索引): 8 { 8 { [ ( 7 , W i l l i a m , M a l e , . . . ) , ( 8 , J o h n , M a l e , . . . ) ] [ ( 5 , M i c h a e l , M a l e , . . . ) , ( 6 , J e s s i c a , F e m a l e , . . . ) ] 4 { [ ( 3 , M a r i a , F e m a l e , . . . ) , ( 4 , S a m a n t h a , F e m a l e , . . . ) ] [ ( 1 , A l i c e , F e m a l e , . . . ) , ( 2 , A n d r e w , M a l e , . . . ) ] s t u d e n t _ n a m e (非聚簇索引): W i l l i a m { W i l l i a m { [ ( S a m a n t h a , 4 ) , ( W i l l i a m , 7 ) ] [ ( M a r i a , 3 ) , ( M i c h a e l , 5 ) ] , J o h n { [ ( J e s s i c a , 6 ) , ( J o h n , 8 ) ] [ ( A l i c e , 1 ) , ( A n d r e w , 2 ) ] \begin{aligned} student\_id(主键聚簇索引):8\begin{cases} 8\begin{cases} [(7, William, Male, ...), (8, John, Male, ...)]\\\\ [(5, Michael, Male, ...), (6, Jessica, Female, ...)] \end{cases}\\\\ 4\begin{cases} [(3, Maria, Female, ...), (4, Samantha, Female, ...)]\\\\ [(1, Alice, Female, ...), (2, Andrew, Male, ...)] \end{cases}\\ \end{cases} \end{aligned}\\\\ \begin{aligned} student\_name(非聚簇索引):William\begin{cases} William\begin{cases} [(Samantha, 4), (William, 7)]\\\\ [(Maria, 3), (Michael, 5)], \end{cases}\\\\ John\begin{cases} [(Jessica, 6), (John, 8)]\\\\ [(Alice, 1), ( Andrew, 2)] \end{cases} \end{cases} \end{aligned} student_id(主键聚簇索引):8 8 [(7,William,Male,...),(8,John,Male,...)][(5,Michael,Male,...),(6,Jessica,Female,...)]4 [(3,Maria,Female,...),(4,Samantha,Female,...)][(1,Alice,Female,...),(2,Andrew,Male,...)]student_name(非聚簇索引):William William [(Samantha,4),(William,7)][(Maria,3),(Michael,5)],John [(Jessica,6),(John,8)][(Alice,1),(Andrew,2)]


三、B+ 树索引

下面是对 m m m 阶 B+ 树的一些说明,不同资料上的定义不尽相同,这里参照维基百科对于 B+ 树的定义:

  • 每个结点至多有 m m m 棵子树, m − 1 m - 1 m1 个关键字。
  • 除根结点外所有内部结点(非叶节点)至少有 ⌊ m / 2 ⌋ \lfloor m/2 \rfloor m/2 棵子树, ⌊ m / 2 ⌋ − 1 \lfloor m/2 \rfloor - 1 m/21个关键字。
  • 所有叶节点都在相同的高度上(绝对平衡),且结构为 [ P 0 k 0 P 1 k 1 … P n − 1 K n − 1 P n ] [P_0 k_0 P_1 k_1 \dots P_{n-1} K_{n-1} P_n] [P0k0P1k1Pn1Kn1Pn](键值交错)。
  • 叶结点本身按关键字大小从小到大链接。

B+ 树相比于 B 树的优势:

  • B+ 树只有叶子节点同时存放键和数据,内部节点只存放键,所以同样大小的磁盘页上可以容纳更多键值对。在相同的数据量下,B+ 树通常具有更扁平的树结构,这意味着在查找操作中需要更少的磁盘 I/O 操作,因此查找效率更高
  • B+ 树的叶子节点之间以双向链表的形式顺序连接,便于范围查找和遍历

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1037935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java流式编程的使用

流式编程的使用步骤 使用流式编程的步骤就是: 设置数据源, 设置数据处理的方式,设置收集结果的方式。 使用filter方法实现过滤条件 例子为下&#xff08;查询年龄大于18的用户&#xff09;: Testpublic void streamTest1() {List<Student> students Arrays.asList(ne…

【Java 基础篇】Java Function 接口详解

在 Java 编程中&#xff0c;Function 接口是一个非常重要的函数式接口&#xff0c;它允许你定义一个接受一个参数并产生结果的函数。Function 接口通常在各种数据处理和转换操作中使用&#xff0c;例如集合处理、流处理以及函数式编程。 本文将详细介绍 Function 接口的使用方…

基于蚁群算法的航线规划

一、背景 二、代码 main.m clear;clc; r21; %21*21 c21; intau20; xstart1; ystart3; %起点 xend20; yend18; %终点 gd1; xt[5,11,8,16,12,15,17,19]; %障碍物 yt[9,15,7,3,12,8,15,12];threat8; NCmax200; %迭代次数%初始化数据 Gamma_A0.9; Rho_A0.2; Alpha_A1; Beta_A3;…

SpringBoot集成easypoi实现execl导出

<!--easypoi依赖&#xff0c;excel导入导出--><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.4.0</version></dependency>通过Exce注解设置标头名字和单…

RocketMQ源码解析(下 )

一、Producer发送消息过程 1、普通发送消息过程 一般发送消息都是new一个DefaultMQProducer&#xff0c;所以先找到DefaultMQProducer类 先进行DefaultMQProducerImpl的初始化&#xff0c;所有Producer的启动过程&#xff0c;最终都会调用到DefaultMQProducerImpl#start方法…

Llama2-Chinese项目:2.3-预训练使用QA还是Text数据集?

Llama2-Chinese项目给出pretrain的data为QA数据格式&#xff0c;可能会有疑问pretrain不应该是Text数据格式吗&#xff1f;而在Chinese-LLaMA-Alpaca-2和open-llama2预训练使用的LoRA技术&#xff0c;给出pretrain的data为Text数据格式。所以推测应该pretrain时QA和Text数据格式…

C++11 - 右值引用

临时空间 临时空间具有常性&#xff0c;什么时候会产生临时空间呢&#xff1f; 1、函数传值返回 把aa拷贝给临时空间&#xff0c;如果是很大的对象并且进行深拷贝&#xff0c;消耗会很大 证明&#xff1a; 这是list模拟实现迭代器的和&#xff01;重载时&#xff0c;while( it…

Secrets

文章目录 主要内容一.命令行创建1.命令行创建代码如下&#xff08;示例&#xff09;: 2.解释 二.环境变量secret1.使用刚才创建的密码&#xff0c;创建Pod并进行尝试。代码如下&#xff08;示例&#xff09;: 2.解释 总结 主要内容 命令行创建环境变量secret 预备知识 Secrets…

车载软件架构 —— AUTOSAR Vector SIP包(二)

车载软件架构 —— AUTOSAR Vector SIP包(二) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在…

【小程序】通过微信提供方法实现条码或二维码的扫描

概述 实现扫码获取信息&#xff0c;对接相应接口 可实现详情查询&#xff0c;已经是完整代码了copy都难么 详细 一、前期准备工作 软件环境&#xff1a;微信开发者工具 官方下载地址&#xff1a;微信开发者工具下载地址与更新日志 | 微信开放文档​编辑 二、程序实现具体步…

机器学习之对神经网络的基本原理的了解

文章目录 神经网络与机器学习神经网络的结点 神经网络与机器学习 神经网络代替模型和用学习规则代替机器学习 神经网络代替模型&#xff1a; 神经网络是一种受到生物神经系统启发的计算模型&#xff0c;它由多个神经元层组成&#xff0c;这些神经元层之间有连接权重&#xff…

测试员有必要转测试开发吗?

为什么很多公司都在招测试开发&#xff1f; 质量保证和软件稳定性&#xff1a;测试开发人员在软件开发生命周期中扮演着关键的角色&#xff0c;他们负责编写和执行测试代码&#xff0c;以确保软件的质量和稳定性。他们可以帮助发现和修复潜在的问题和缺陷&#xff0c;提高软件…

现在公司都在用的CI/CD框架到底是什么?

目录 一&#xff0c;CI/CD到底是什么&#xff1f; 二&#xff0c;为什么要用CI/CD&#xff1f; 三&#xff0c;CI/CD的优缺点&#xff1f; 四&#xff0c;CI/CD都基于什么服务搭建&#xff1f; 五&#xff0c;CI/CD是否适用于所有类型的软件开发&#xff1f; 一&#xff0…

Quartus的2FSK调制解调verilog

名称&#xff1a;Quartus的2FSK调制解调verilog 软件&#xff1a;Quartus 语言&#xff1a;Verilog 要求&#xff1a;使用verilog实现2FSK的调制和解调&#xff0c;并进行仿真 代码下载&#xff1a;Quartus的2FSK调制解调verilog_Verilog/VHDL资源下载 代码网&#xff1a;…

SpringBoot之响应处理

文章目录 前言一、返回值处理器ReturnValueHandler流程关于HttpMessageConverters的初始化ReturnValueHandler与MappingJackson2HttpMessageConverter关联 二、内容协商内容协商原理底层源码 三、自定义MessageConverter总结 前言 包括返回值处理器ReturnValueHandler、内容协…

OpenGLES:绘制一个颜色渐变的圆

一.概述 今天使用OpenGLES实现一个圆心是玫红色&#xff0c;向圆周渐变成蓝色的圆。 本篇博文的内容也是后续绘制3D图形的基础。 实现过程中&#xff0c;需要重点关注的点是&#xff1a;如何使用数学公式求得图形的顶点&#xff0c;以及加载颜色值。 废话不多说&#xff0c…

FPGA的BPSK调制verilog

名称&#xff1a;BPSK调制verilog 软件&#xff1a;Quartus 语言&#xff1a;Verilog 要求&#xff1a; 一、设计说明 BPSK调制广泛应用于卫星通信、移动通信等领域。本题目要求设计一个基于直接数字频率合成技术的BPSK调制器&#xff0c;实现对输入周期数字比特流的BPSK调…

LVGL_基础知识

LVGL_基础知识 1、设置对象大小 lv_obj_t * obj lv_obj_create(lv_scr_act()); //lv_obj_set_width(obj, 300); //lv_obj_set_height(obj, 500); lv_obj_set_size(obj,200, 240);//和上面两句的效果一样2、获取对象大小 lv_obj_t * obj lv_obj_create(lv_scr_act()); //lv…

GPS硬件坐标转百度地图坐标

在地图定位开发中&#xff0c;许多定位模块输出坐标系是国际标准 WGS-84 坐标系&#xff0c;所以开发者在国内常见地图定位时&#xff0c;会发现与实际情况有几十米的误差。这并非模块问题&#xff0c; 而是国内地图采用了非标坐标系所致。 国内常见地图如高德地图使用 GCJ-02 …

Kubernetes集群+Keepalived+Nginx+防火墙 实例

目录 实验前期规划 1.拓扑图结构 2.实验要求 3.实验环境规划 一.kubeadm 部署 K8S 集群架构 1.环境准备 2.三个节点安装docker 3.三个节点安装kubeadm&#xff0c;kubelet和kubectl 4.部署K8S集群 &#xff08;1&#xff09;初始化 4.部署K8S集群 &#xff08;1&am…