【MySQL】09.索引

news2025/5/26 6:41:22

索引是用来提高数据库的性能的,但查询速度的提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO。所以它的价值在于提高一个海量数据的检索速度。

1. 认识磁盘

MySQL 给用户提供存储服务,而存储的都是数据,数据在磁盘这个外设当中。磁盘是计算机中的一个机械设备,相比于计算机其他电子元件,磁盘效率是比较低的,在加上IO本身的特征,可以知道提高效率是 MySQL 的一个重要话题。

具体的介绍请看这篇【Linux系统与系统编程】11.磁盘文件系统_硬盘文件系统-CSDN博客

磁盘随机访问(Random Access)与连续访问(Sequential Access)

随机访问

本次IO所给出的扇区地址和上次IO给出扇区地址不连续,这样的话磁头在两次IO操作之间需 要作比较大的移动动作才能重新开始读/写数据。

连续访问

本次IO给出的扇区地址与上次IO结束的扇区地址是连续的,那磁头就能很快的开始这次 IO操作,这样的多个IO操作称为连续访问。

因此尽管相邻的两次IO操作在同一时刻发出,但如果它们的请求的扇区地址相差很大的话也只能称为随机访问,而非连续访问。

磁盘是通过机械运动进行寻址的,随机访问不需要过多的定位,故效率比较高。

2. MySQL 与磁盘交互基本单位

MySQL 作为一款应用软件,可以想象成一种特殊的文件系统。它有着更高的IO场景,为了提高基本的IO效率,MySQL进行IO的基本单位是16KB。这个基本数据单元,在MySQL这里叫做page。

MySQL 中的数据文件是以page为单位保存在磁盘当中的,而 MySQL 的 CURD 操作需要通过计算找到对应的插入位置,或者找到对应要修改或者查询的数据。而只要涉及计算,就需要CPU参与,而为了便于CPU参与,一定要能够先将数据移动到内存当中。 所以在特定时间内,数据一定是磁盘中有,内存中也有。后续操作完内存数据之后,以特定的刷新 策略,刷新到磁盘。而这时,就涉及到磁盘和内存的数据交互,也就是IO了。而此时IO的基本单位就是Page。 为了更好的进行上面的操作, MySQL 服务器在内存中运行的时候,在服务器内部,就申请了被称为 Buffer Pool 的的大内存空间,来进行各种缓存。其实就是很大的内存空间,来和磁盘数据进行IO交互。 为何更高的效率,一定要尽可能的减少系统和磁盘IO的次数。

mysql> show global status like 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_page_size | 16384 | -- 16 * 1024 = 16384
+------------------+-------+
1 row in set (0.00 sec)

3. 索引的理解

3.1 初识索引

首先我们建立一张测试的数据表:

-- 创建测试表
mysql> create table user(
    -> id int primary key, -- 要添加主键才能产生索引
    -> age int not null,
    -> name varchar(20) not null
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> show create table user \G;
*************************** 1. row ***************************
       Table: user
Create Table: CREATE TABLE `user` (
  `id` int NOT NULL,
  `age` int NOT NULL,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

-- 插入数据(不按顺序插入)
mysql> insert into user (id, age, name) values(3, 18, '杨过');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user (id, age, name) values(4, 16, '小龙女');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user (id, age, name) values(2, 26, '黄蓉');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user (id, age, name) values(5, 36, '郭靖');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user (id, age, name) values(1, 56, '欧阳锋');
Query OK, 1 row affected (0.01 sec)

-- 查看插入结果
mysql> select * from user;
+----+-----+-----------+
| id | age | name      |
+----+-----+-----------+
|  1 |  56 | 欧阳锋    |
|  2 |  26 | 黄蓉      |
|  3 |  18 | 杨过      |
|  4 |  16 | 小龙女    |
|  5 |  36 | 郭靖      |
+----+-----+-----------+
5 rows in set (0.01 sec)

我们可以发现我们随机插入的数据,但是插入的数据确是按照id排好序的,这是为什么呢?这就是索引的作用。

3.2 理解索引

MySQL和磁盘进行IO交互的时候为什么要采用Page的方案进行交互呢?为什么不用加载呢?     

对应上面的5条记录,如果MySQL要查找id = 2的记录,第一次加载id = 1 ,第二次加载id = 2 ,一次一条记录,那么就需要2次IO。如果要找id = 5 就需要5次IO。 但如果这5条(或者更多)都被保存在一个Page中(16KB,能保存很多记录),那么第一次IO查找id = 2的时候,整个Page会被加载到MySQL的Buffer Pool中,即只是完成了一次IO,这样在查找id = 1,3,4,5 等数据时就完全不需要进行IO了,而是直接在内存中进行了。所以,就在单Page里面,大大减少了IO的次数。 

• 单个page

MySQL 中要管理很多数据表文件需要先描述,在组织
 

在 MySQL 中所有的page都是16KB ,使用 prev 和 next 构成双向链表。MySQL 会默认按照主键给我们的数据进行排序,从上面的Page内数据记录可以看出,数据是有序且彼此关联的。

• 多个page

上面页模式在查询某条数据的时候直接将一整页的数据加载到内存中以减少硬盘IO次数,从而提高性能。可以看到现在的页模式内部采用了链表的结构,前一条数据指向后一条数据,本质上还是通过数据的逐条比较来取出特定的数据。

如果有1千万条数据的话,就一定需要多个Page来保存千万条数据,多个Page彼此使用双链表链接起来,而且每个Page内部的数据也是基于链表的。那么查找特定一条记录也一定是线性查找。这效率也太低了吧。

这就引出了多page情况:

• 页目录

对于多page情况,如果我们想要查看某一个page的话就需要遍历查询啊,这效率也有点低吧。

于是引入了页目录:

也就是说存在一个目录页来管理页目录,目录页中的数据存放的就是指向的那一页中最小的数据。其实目录页的本质也是页,普通页中存的数据是用户数据,而目录页中存的数据是普通页的地址。

可是我们每次检索数据的时候该从哪里开始呢?虽然顶层的目录页少了,但是还要遍历啊?可以在加目录页。

上述结构就是传说中的B+树!至此,我们已经给我们的表user构建完了主键索引。随便找一个id=?我们发现,现在查找的Page数一定减少了,也就意味着IO次数减少了,那么效率也就提高了。

3.3 B树 vs B+树

• B树

• B+树

我们可以看出:
• B树节点,既有数据,又有Page指针,而B+树只有叶子节点有数据,其他目录页只有键值和 Page指针。
• B+树叶子节点全部相连,而B没有。
• B+树节点不存储data,这样一个节点就可以存储更多的key。可以使得树更矮,所以IO操作次数更少。 叶子节点相连,更便于进行范围查找 。

3.4 聚簇索引 VS 非聚簇索引

MyISAM 引擎同样使用B+树作为索引结果,叶节点的data域存放的是数据记录的地址。下图为 MyISAM 表的主索引, Col1 为主键。

 MyISAM 最大的特点是将索引Page和数据Page分离,也就是叶子节点没有数据,只有对应数据的地址。相较于 InnoDB 索引, InnoDB 是将索引和数据放在一起的。

MyISAM 这种用户数据与索引数据分离的索引方案,叫做非聚簇索引。InnoDB 这种用户数据与索引数据在一起索引方案,叫做聚簇索引。

下面是聚簇索引和非聚簇索引的验证:

 4. 索引操作

4.1 创建索引

• 创建主键索引

-- 1.在创建表的时候,直接在字段名后指定 primary key
create table user1(
id int primary key, 
name varchar(30)
);

-- 2.在创建表的最后,指定某列或某几列为主键索引
create table user2(
id int, name varchar(30), 
primary key(id)
); 

-- 3.创建表以后再添加主键
create table user3(
id int, 
name varchar(30)
);
alter table user3 add primary key(id);

• 创建唯一索引

-- 1.在表定义时,在某列后直接指定unique唯一属性。
create table user4(
id int primary key, 
name varchar(30) unique
);

-- 2.创建表时,在表的后面指定某列或某几列为unique
create table user5(
id int primary key, 
name varchar(30), 
unique(name)
);

-- 3.创建表以后再添加唯一键
create table user6(
id int primary key, 
name varchar(30)
);
alter table user6 add unique(name);

• 创建普通索引

-- 1.在表的定义最后,指定某列为索引
create table user8(
id int primary key,
name varchar(20),
email varchar(30),
index(name) 
);

-- 2.创建完表以后指定某列为普通索引
create table user9(
id int primary key, 
name varchar(20), 
email varchar(30)
);
alter table user9 add index(name); 

-- 3.创建一个索引名为 idx_name 的索引 
create table user10(
id int primary key, 
name varchar(20), 
email varchar(30)
);
create index idx_name on user10(name);

• 创建全局索引

当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。MySQL提供全文索引机制,但是有要求,要求表的存储引擎必须是MyISAM,而且默认的全文索引支持英文,不支持中文。如果对中文进行全文检索,可以使用sphinx的中文版(coreseek)。

CREATE TABLE articles (
 id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
 title VARCHAR(200),
 body TEXT,
 FULLTEXT (title,body)
)engine=MyISAM;

4.2 查询索引

-- 1.show keys from 表名;
mysql> show keys from user\G;
*************************** 1. row ***************************
        Table: user
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 4
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
1 row in set (0.01 sec)

ERROR: 
No query specified

-- 2.show index from 表名;
mysql> show index from user\G;
*************************** 1. row ***************************
        Table: user
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 4
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
1 row in set (0.00 sec)

ERROR: 
No query specified

-- 3.desc 表名
mysql> desc user;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | NO   | PRI | NULL    |       |
| age   | int         | NO   |     | NULL    |       |
| name  | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

4.3 删除索引

-- 1. 删除主键
alter table 表名 drop primary key;

-- 2. 删除普通索引
alter table 表名 drop index 索引名;

-- 3. drop删除
drop index name on user8;

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

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

相关文章

【备忘】 windows 11安装 AdGuardHome,实现开机自启,使用 DoH

windows 11安装 AdGuardHome,实现开机自启,使用 DoH 下载 AdGuardHome解压 AdGuardHome启动 AdGuard Home设置 AdGuardHome设置开机自启安装 NSSM设置开机自启重启电脑后我们可以访问 **http://127.0.0.1/** 设置使用 AdGuardHome DNS 效果图 下载 AdGua…

[Windows] 游戏常用运行库- Game Runtime Libraries Package(6.2.25.0409)

游戏常用运行库 合集 整合了许多游戏会用到的运行库,支持 Windows XP – Windows 11 系统,并且支持自动检测系统勾选推荐的运行库,方便快捷。 本版特点: By:mefcl 整合常见最新游戏所需运行库 根据系统自动勾选推荐…

(九)PMSM驱动控制学习---高阶滑膜观测器

在之前的文章中,我们介绍了永磁同步电机无感控制中的滑模观测器,但是同时我们也认识到了他的缺点:因符号函数带来的高频切换分量,使用低通滤波器引发相位延迟;在本篇文章,我们将会介绍高阶滑模观测器的无感…

25年上半年五月之软考之设计模式

目录 一、单例模式 二、工厂模式 三、 抽象工厂模式 四、适配器模式 五、策略模式 六、装饰器模式 ​编辑 考点:会挖空super(coffeOpertion); 七、代理模式 为什么必须要使用代理对象? 和装饰器模式的区别 八、备忘录模式 一、单例模式 这个…

Mongo DB | 多种修改数据库名称的方式

目录 方法一:使用 mongodump 和 mongorestore 命令 方法二:使用 db.copyDatabase() 方法 方法三:使用 MongoDB Compass 在 MongoDB 中,更改数据库名称并不是一个直接的操作,因为 MongoDB 不提供直接重命名数据库的命…

QListWidget的函数,信号介绍

前言 Qt版本:6.8.0 该类用于列表模型/视图 QListWidgetItem函数介绍 作用 QListWidget是Qt框架中用于管理可交互列表项的核心组件,主要作用包括: 列表项管理 支持动态添加/删除项:addItem(), takeItem()批量操作:addItems()…

EtherNet/IP机柜内解决方案在医疗控制中心智能化的应用潜能和方向分析

引言 在数智化转型浪潮席卷各行各业的今天,医疗领域同样面临着提升运营效率、改善患者体验和加强系统可靠性的多重挑战。Rockwell Automation于2025年5月20日推出的EtherNet/IP机柜内解决方案,为医疗中心的自动化升级提供了一种创新路径。本报告将深入分析这一解决方案的核心…

【结构设计】以3D打印举例——持续更新

【结构设计】以立创EDA举例——持续更新 文章目录 [TOC](文章目录) 前言立创EDA官网教程一、3D外壳绘制二、3D外壳渲染三、3D外壳打印1.3D打印机——FDM2.3D打印机——光固化 四、3D外壳LOG设计1.激光雕刻机 总结 前言 提示:以下是本篇文章正文内容,下面…

MySQL中的重要常见知识点(入门到入土!)

基础篇 基础语法 添加数据 -- 完整语法 INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);-- 示例 insert into employee(id,workno,name,gender,age,idcard,entrydate) values(1,1,Itcast,男,10,123456789012345678,2000-01-01) 修改数据 -- 完整语法 UPDA…

理解全景图像拼接

1 3D到2D透视投影 三维空间上点 p 投影到二维空间 q 有两种方式:1)正交投影,2)透视投影。 正交投影直接舍去 z 轴信息,该模型仅在远心镜头上是合理的,或者对于物体深度远小于其到摄像机距离时的近似模型。…

云原生安全基石:Linux进程隔离技术详解

🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 进程隔离是操作系统通过内核机制将不同进程的运行环境和资源访问范围隔离开的技术。其核心目标在于: 资源独占:确保…

基于PySide6与pycatia的CATIA几何阵列生成器开发实践

引言:参数化设计的工业价值 在航空航天、汽车制造等领域,复杂几何图案的批量生成是模具设计与机械加工的核心需求。传统手动建模方式存在效率低下、参数调整困难等问题。本文基于PySide6+pycatia技术栈,实现了一套支持​​动态参数配置​​、​​智能几何阵列生成​​的自动…

Linux学习心得问题总结(三)

day09 文件权限篇 文件权限的属性有哪些?我们应如何理解这些属性? 文件权限的属性包括可读(r)、可写(w)、可执行(x)三种权限,根据文件类型可分为普通文件(.…

Anthropic推出Claude Code SDK,强化AI助理与自动化开发整合

Anthropic发布Claude Code SDK,协助开发团队将人工智慧助理整合进自动化开发流程,支援多轮对话、MCP协定及多元格式。 Anthropic推出Claude Code SDK,提供开发者与企业一套可程序化整合Claude AI助理至开发流程的工具。此SDK以命令列介面为基…

6.4.1最小生成树

知识总览 生成树(一定是连通的): 是连通的无向图的一个子图,子图包含这个无向图的所有顶点有n-1条边(少一条边,生成树就不连通了)即为生成树,一个连通图可能有多个生成树 最小生成树(最小代价树): 只有连通的无向图才…

DARLR用于具有动态奖励的推荐系统的双智能体离线强化学习(论文大白话)

1. 概述 离线强化学习是现在强化学习研究的一个重点。相比与传统的强化学习它不需要大量的实时交互数据,仅仅依赖历史交互日志就可以进行学习。本文就是将离线强化学习用于推荐系统的一篇文章。 这篇文章主要解决的核心问题有以下几个: 1)…

第35节:PyTorch与TensorFlow框架对比分析

引言 在深度学习领域,PyTorch和TensorFlow无疑是当前最受欢迎的两大开源框架。 自2015年TensorFlow由Google Brain团队发布,以及2016年Facebook的AI研究团队推出PyTorch以来,这两个框架一直在推动着深度学习研究和工业应用的发展。 本文将从多个维度对这两个框架进行详细对…

企业级智能体 —— 企业 AI 发展的下一个风口?

在AI技术迅猛发展的当下,企业对AI的应用不断深入。企业级智能体逐渐受到关注,它会是企业AI发展的下一个风口吗?先来看企业典型的AI应用场景,再深入了解企业级智能体。 企业典型AI应用场景 1. 内容生成:2025年&#xf…

【软考向】Chapter 2 程序设计语言基础知识

程序设计语言概述低级语言 —— 机器指令、汇编语言高级语言 ——翻译:汇编、解释和编译语言处理程序基础 —— 翻译给计算机,汇编、编译、解释三类编译程序基本原理 —— 词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成文法和语言的形式描述确定的有限…

JavaWeb:SpringBootAOP切面实现统计方法耗时和源码解析

介绍 快速入门 1.导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>2.切面类java Slf4j Aspect Component public class RecordTimeApsect {/*** 统计耗…