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

MySQL(索引)

目录

一 索引是什么?

二 硬件理解

1. 磁盘存储结构(简化版)

2. 定位扇区

3. 随机定位/连续定位

三 软件理解

四 B+树

1. 下面看看一个现象

2. 引入页目录

3. 为什么MySQL不采用其他的数据结构来作为索引结构?

4. 索引最左匹配原则/索引覆盖

五 索引的常见操作/索引类型

1. 主键

2. 唯一键/普通索引

4. 全文索引


一 索引是什么?

比如在数组里查找特定的值,直接[ ]访问即可,比如采用链表,就需要线性遍历,在找的过程中就相当于一次索引,不同的数据结构加他本身的算法来决定索引的效率,也就是索引=数据结构+算法,如果没有索引进行查找可能导致效率大大降低。

二 硬件理解

1. 磁盘存储结构(简化版)

MySQL里面的表信息/库信息/其他信息都是存放在磁盘上的,下面来看看磁盘的存储结构。

  • 每一个盘面里面有很多个环状的面,称为磁道,很多个盘面洛起来对应的磁道看起来就是个柱面形状,所以也可以叫柱面,磁道被分为很多区域,称为扇区,距离中心点跃进扇区越小,越远越大,每个磁面(磁盘分正方面)配对一个磁头,用来定位磁道。
  • 所有的扇区一般是512字节,虽然越靠近中心点越小,越考外处越大,但都是512字节(可能密度不同)。
2. 定位扇区

文件都在磁盘上,存放的数据都在一个一个的扇区中,怎么找到一个扇区?

首先需要找到对应的磁头,再通过磁头左右摆动定位对应的磁道,再通过盘片高速旋转定位某个扇区,这样的寻址方式称为CHS寻址,这是磁盘的寻址方式,但系统和磁盘交互不同,系统和磁盘交互是以4kb为基本单位,即8个扇区,把这8个扇区抽象成逻辑块地址,再通过逻辑块来转换成CHS地址,相当于给一个逻辑块地址,根据这个逻辑块地址转换成CHS地址让磁盘去匹配扇区。

3. 随机定位/连续定位

随机访问:如果2次IO的扇区地址相差很大,第二次磁头必须重新定位磁道,在根据盘片定位扇区,伴随物理的移动,效率低下。

连续访问:如果2次IO的扇区地址连续,一次定位连续读取即可,虽然是2次IO,但磁盘只需寻址一次,然后连续读取。

即使多次IO同时进行,但扇区地址相差很大,也只能随机访问。

三 软件理解

1. MySQL与磁盘交互的基本单位

MySQL与磁盘IO交互的基本单位是16kb,这是在逻辑上的角度,因为MySQLd是在内存中的,属于应用层,访问磁盘硬件,必须通过操作系统进行交互,而操作系统IO交互的基本单位是4kb,也就是说操作系统内的文件缓冲区设置为16kb,在从磁盘读取4kb,读4次,在刷新到MySQL预先开辟的buffpoo缓冲区里,所以MySQL与操作系统page的比例为1:4,所以提交效率指的是IO的次数,就好比如读取100k,分一次读100k和分100次读1k,IO交互越少效率越高。

四 B+树

1. 下面看看一个现象

创建测试表

create table if not exists user (
id int primary key, --一定要添加主键哦,只有这样才会默认生成主键索引
age int not null,
name varchar(16) not null
);

id作为主键列,当乱序插入时,mysql查询出来的结构默认就是有序的了,为什么?谁做的?

重谈page

mysqld服务启动会预先开辟一段空间,将来接收一个个的page,page多了,肯定要对page进行管理,比如脏页,未使用的页,待刷新的页等,比如页与页之间用链表管理起来。

// 简单的page伪代码
struct page
{
    struct page* _prev;
    struct page* _next;
    char buffPoll[num];
}// 16k

上述的结果为什么会有序?

2. 引入页目录

目录再熟悉不过了,书开始的几页/十几页都是一个个的目录,用来记录每个专题的起始页和结束页,有了这个目录就不需要在线性一个个的去翻页,直接查页目录,在到对应的页去查找内容,所以,页目录本身就是管理一个个的页,是用空间换时间的做法。

page之间是用链表关联起来的,如果数据是有序的,page内部在记录对应的主键列的比如最小值和最大值,即页内目录,就能检测要查找的数据在不在这个区间,如果在直接遍历该page即可,不在就去下一个页继续进行比较,也就是不用在page内部进行遍历而是在page之间进行遍历,间接的过滤掉了不合适的page达到效率提高。

那么问题来了,如果page过多且查找的数据在靠后面,也成了线性遍历,怎么办?引入页目录。

页目录也是在page当中,只不过他存放的是页内目录对应的page的最小主键值和指向对应的page的指针,管理的是页,页内目录管理的是行,如果数据在右边的目录,直接筛掉左边的所有page,效率大大提升,那么一个页目录大小是多少呢?忽略页目录之间的链表衔接,每个页目录的一个个数据都是要指向叶子节点的,在存储对应的最小主键值,也就是12字节,一个页目录能存16k*1024=16,384字节,在除以12=1,365个叶子节点,在*16=21,840k,在/1024=21M,可见引入页目录能大大提高对page的查找效率,如果叶子节点还是太长了,继续引入二级页目录.....

这种存储结构称为 B+

  • 叶子节点存数据,非叶子节点存page和对应的主键值(KV),非叶子节点只存page,那么能存的page会变多,非叶子节点就会变得少,这种树形结构看起来就是很矮很胖
  • 叶子节点用指针关联起来,主要支持进行范围查找
3. 为什么MySQL不采用其他的数据结构来作为索引结构?

链表:线性遍历,不合适

二叉搜索树:极端情况退化成链表结构,不合适

红黑树/AVL树:虽然都是绝对平衡/相对平衡,树的高度就会越高,途径非叶子节点就会越多,IO次数就越多,B+树高度低,IO次数就越少,所以B+树更适合

哈希表:虽然哈希表平均查找是O(1),但不能高效的进行范围查询,可能要哈希n次,B+树一次遍历连续读取即可,还是B+树更合适

B树 VS B+树

B树

  • 叶子节点没有指针关联起来,不能高效的进行范围查找,要频繁的遍历这棵树
  • 非叶子节点即存page也存数据,那么一个页目录能存的page就越少,页目录就越多,树高度就相比于B+树越高,所以B+树总体更优

聚簇索引 VS 非聚簇索引

Innodb和MyISAM都采用B+树作为索引结构,但MyISAM的叶子节点不存放数据,而是存放指向数据的指针。

这种将数据和索引数据分离用指针关联起来就是非聚簇索引,将数据放在和索引数据里面就是聚簇索引。

如果有其他的非主键索引,在非聚簇看来没有区别,都是遍历到叶子节点根据地址找到数据,但如果是聚簇索引看来,非主键索引叶子节点存放的不是数据,而是数据对应的主键值,在根据主键值去主键构建的B+树进行查找,这种查找方式叫做回表查询,因为如果非主键索引叶子节点也存数据的话,会浪费空间。

4. 索引最左匹配原则/索引覆盖

如果索引是复合索引,复合索引进行查找只能从左往右进行查找,比如 A B C 构建索引,如果按A,AB,ABC筛选会用到索引,B,C,BC不会用到索引,如果查找BC,按A筛选,找到A直接返回,因为BC包含在索引中,就不用进行回表,称为索引覆盖。

五 索引的常见操作/索引类型

1. 主键
// 创建表名指定
create table (id int primary key);
create table (id int primary key,primary key(id));

// 已有表名指定
alter table 表名 add primary key(列名);

// 移除主键
alter table 表名 drop primary key;

什么样的字段适合建立索引?

频繁被查询的,频繁出现在where筛选条件的,唯一性好,频繁不更新的字段适合建立索引

2. 唯一键/普通索引
// 创建表指定
create table 表名(id int unique);
create table 表名(id int,unique(id));


// 已有表指定(唯一索引)
alter table 表名 add unique(表名);
// 已有表指定(普通索引)
alter table 表名 add index(表名);

// 移除唯一/普通索引
alter table 表名 drop index 表名;
4. 全文索引

上述的索引单值某一列/多列匹配,有没有一种可能要找的是一列当中的某个字段?比如想查找文本里面的某个信息,支持这个特性就要添加全文索引,只有MyISAM支持全文索引,MyISAM不支持事务,一般适用于高并发读场景。

// 创建全文索引
create (列名,FULLTEXT(列名))engine=myisam;

// 用全文索引
select *from 表名 where match(列名) against(查询数据);

相关文章:

  • 华为ISC+战略规划项目数字化转型驱动的智慧供应链革新(169页PPT)(文末有下载方式)
  • 架构师面试(十七):总体架构
  • numpy学习笔记4:np.arange(0, 10, 2) 的详细解释
  • 深度学习零碎知识
  • 【C语言】自定义类型:结构体
  • Android 15 获取网络切片信息的标准接口
  • 《C语言中的ASCII码表:解锁字符与数字的桥梁》
  • Netty基础—Netty实现消息推送服务
  • go语言中数组、map和切片的异同
  • Mobile-Agent-V:通过视频引导的多智体协作学习移动设备操作
  • PCDN 在去中心化互联网中的角色
  • 个人.clang-format配置,适合Linux C/C++
  • 韩顺平教育-家居网购
  • 搜广推校招面经五十四
  • 【从0到1学Redis】Redis基础篇
  • 生信分析服务作图TCGA/GEO数据库挖掘细胞测序转录学代做指导辅导
  • 靶场(十三)---小白心得思路分享---Levram
  • 基于Netty实现高性能HTTP反向代理
  • Python-素数
  • 提示词prompt如何写
  • 原国家有色金属工业局副局长黄春萼逝世,享年86岁
  • 游客曝九寨沟打网约车被出租车围堵,景区回应:当地无合规网约车
  • 深入贯彻中央八项规定精神学习教育中央指导组培训会议召开
  • 上海开花区域结果,这项田径大赛为文旅商体展联动提供新样本
  • 上海112位全国劳动模范和先进工作者接受表彰,樊振东榜上有名
  • 我驻阿巴斯总领馆:将持续跟踪港口爆炸事件进展,全力确保中方人员安全