Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > mysql页和索引

MySQL数据库页与索引示例详解

作者:Boop_wu

文章主要内容是详细介绍了MySQL索引的工作原理和使用方法,文章介绍了如何通过执行计划查看SQL是否使用了索引,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

MySQL 索引是提升查询效率的核心机制 , 基于特定的数据结构(B+树,哈希等)对数据进行预排序和快速定位 , 避免全表扫描

一.索引使用哪种数据结构

1.哈希索引

2.B+树索引(最常用)

2.1 B+树简介

B+树是一种经常用于数据库和文件系统等场合的平均查找树 , MySQL 索引采用的数据结构 , 以 4 阶 B+树为例

在二叉搜索树的基础上可以有效控制树高 , 也就意味着在在相同数据量的情况下 可以有效减少 IO 次数 , 从而提升效率

2.2 B+ 树特点

2.3 B+树与 B 树的对比

  1. 叶子结点之间有一个相互连接的引用 , 使数据连续去 , 且相互链接 , 便于区间查找和搜索 , 并且在 MySQL中使用的是双向链表
  2. 非叶子结点的值都包含在叶子节点中 , MySQL 非叶子结点之保存了对叶子结点的引用 , 没有保存真实数据 , 所有的真实数据都保存在叶子结点中
  3. 对于 B+树而言 , 在相同树高的情况下 , 查找任意元素的时间复杂度都是一样的 , 性能均衡

2.4 B+树索引的使用

2.5 B+树在 MySQL 索引中的应用

非叶子结点保存索引数据 , 叶子结点保存真实数据

二 . 索引中的页

1.索引与页的关系

MySQL 索引(B+树)的每一层结点都是独立的页 , 通过页内指针和页间链表组织 , 实现高效数据查询

# B+ 树索引与页的对应关系
┌─────────────────────────────────────────────────────┐
│  根节点页(16KB) - 非叶子节点                      │
│  ┌───────────┬───────────┬───────────┬───────────┐  │
│  │ 键值:100  │ 键值:200  │ 键值:300  │ 键值:400  │  │
│  │ 指针:页2  │ 指针:页3  │ 指针:页4  │ 指针:页5  │  │
│  └───────────┴───────────┴───────────┴───────────┘  │
└─────────────────────────────────────────────────────┘
            ↓           ↓           ↓           ↓
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 子节点页2     │ │ 子节点页3     │ │ 子节点页4     │ │ 子节点页5     │
│ (非叶子节点) │ │ (非叶子节点) │ │ (非叶子节点) │ │ (非叶子节点) │
└───────────────┘ └───────────────┘ └───────────────┘ └───────────────┘
            ↓           ↓           ↓           ↓
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 叶子节点页10  │ │ 叶子节点页11  │ │ 叶子节点页12  │ │ 叶子节点页13  │
│ (聚簇索引:  │ │ (聚簇索引:  │ │ (聚簇索引:  │ │ (聚簇索引:  │
│  存储完整数据) │ │  存储完整数据) │ │  存储完整数据) │ │  存储完整数据) │
│  ┌─────────┐  │ │  ┌─────────┐  │ │  ┌─────────┐  │ │  ┌─────────┐  │
│  │ id:1-99 │  │ │  │id:100-199│  │ │  │id:200-299│  │ │  │id:300-399│  │
│  └─────────┘  │ │  └─────────┘  │ │  └─────────┘  │ │  └─────────┘  │
│  前指针:null  │ │  前指针:页10  │ │  前指针:页11  │ │  前指针:页12  │
│  后指针:页11  │ │  后指针:页12  │ │  后指针:页13  │ │  后指针:null  │
└───────────────┘ └───────────────┘ └───────────────┘ └───────────────┘

2.为什么使用页 ?

在.ibj 文件中最重要的结构体就是页 , 页是内存与磁盘交互的最小单元 , 默认大小是 16 KB , 每次内存与磁盘交互至少读一页 , 所以在磁盘中每个页内部的地址都是连续的 , 之所 以这样做,是因为在使⽤数据的过程中,根据局部性原理,将来要使⽤的数据⼤概率与当前访问的 数据在空间上是临近的,所以⼀次从磁盘中读取⼀⻚的数据放⼊内存中,当下次查询的数据还在这 个⻚中时就可以从内存中直接读取,从⽽减少磁盘I/O提⾼性能

局部性原理: 是指程序在执⾏时呈现出局部性规律,在⼀段时间内,整个程序的执⾏仅限于程序中的某⼀部 分。相应地,执⾏所访问的存储空间也局限于某个内存区域,局部性通常有两种形式:时间局部 性和空间局部性。

时间局部性(TemporalLocality):如果⼀个信息项正在被访问,那么在近期它很可能还会被再 次访问。

空间局部性(SpatialLocality):将来要⽤到的信息⼤概率与正在使⽤的信息在空间地址上是临 近的

  • 每个页即使没有数据也会使用 16KB 空间 , 同时与索引的 B+树种的结点对应

3 索引结点与页之间的关系

4 数据页的基本结构

① 文件头部 file header(38 字节)

page number : 页的唯一编号 , 用于定位页在磁盘上的位置

prev page / next page : 上一页/下一页的编号 , 形成双向链表(方便范围查询)

page typr : 页的类型(索引页 , 数据页 , undo 日志页)

checksum : 页的校验和 , 用于验证数据的完整性

② 数据页头 page header(56 字节)

page level : 当前页在 B+ 树种的层级

record count : 页内存储的用户记录数

free space offset : 空闲空间的起始偏移量(标识空闲空间的位置)

directory slot count : page directory 中的槽数量 (用于快速定位记录)

③infimum + supremum(最小/最大记录 , 固定存在)

④User Records(用户记录)

⑤Free Space(空闲空间)

⑥Page Directory(页面目录)

⑦File Trailer(文件尾部,8 字节)

Checksum:与 File Header 中的校验和一致,用于比对验证。
LSN(Log Sequence Number):页的日志序列号,关联事务日志,确保数据持久化

5. 三层 B + 树的存储容量计算

三层 B + 树结构为 “根节点索引页 → 二级节点索引页 → 叶子节点数据页”因此总记录数为:根节点索引记录数 × 二级节点索引记录数 × 叶子节点数据记录数 = 1170 × 1170 × 16 = 21,902,400

三层树高的 B + 树可存储约 2190 万条记录,且检索时只需三次 I/O(对应树的三层访问),体现了 B + 树在大规模数据存储与高效检索上的优势

三 . 索引的分类

1.按功能与约束划分

① 主键索引 ( PRIMARY KEY)

② 普通索引 (INDEX)

③ 唯一索引 (UNIQUE)

④ 联合索引(多列索引)

⑤ 全文索引(按数据结构划分)

2.按存储方式划分 (InnoDB 引擎)

① 聚簇索引(clustered index)

索引与数据存储在一起 , 叶子结点即数据记录 , 仅主键索引是聚簇 索引

优势 查询主键时无需徽标 , 效率高 ; 劣势 主键更新会导致数据移动 , 影响性能

② 二级索引(secondary index)

③ 索引覆盖

四.使用索引

1.查看索引

① 方式 1 : show keys from 表名

② 方式 2 : show index from 表名

③ 方式 3 : 简要信息 : desc 表名

查看索引信息

2.自动创建

3.手动创建

① 主键索引

create table t_test_pk(
  id bigint primary key auto_increment,
  name varchar(20)
);

create table t_test_pk1(
  id bigint auto_increment,
  name varchar(20),
  primary key(id)
);

语法 : alter table 表名 [add | modify | drop] 要修改的内容

示例 : alter table t_test_pk2 modify id bigint auto_increment;

create table t_test_pk2(
  id bigint,
  name varchar(20)
);
alter table t_test_pk2 add primary key(id);#为表中添加主键 , 并指定ID

② 唯一索引

create table t_test_uk(
  id bigint primary key auto_increment,
  name varchar(20) unique
);

create table t_test_uk1(
  id bigint primary key auto_increment,
  name varchar(20),
  unique (name)
);

create table t_test_uk2(
  id bigint primary key auto_increment,
  name varchar(20)
);
alter table t_test_uk2 add unique (name);

4.普通索引

按创建的时机分为两种

① 创建表时指定索引列

create table t_test_index(
  id bigint primary key auto_increment,
  name varchar(20) unique,
  sno varchar(10),
  index(sno)
);

② 修改表中的列为普通索引

create table t_test_index1(
  id bigint primary key auto_increment,
  name varchar(20),
  sno varchar(10)
);
alter table t_test_index1 add index(sno);

③ 单独创建索引并指定索引名

语法 : create index 索引名(一般为 index_ 表名 _ 列名) on 表名(列名);

create table t_test_index2(
  id bigint primary key auto_increment,
  name varchar(20),
  sno varchar(10) 
);
create index index_name on t_test_index2(sno);

5.创建复合索引

创建语法与创建普通索引相同 , 只不过指定多个列 , 列与列之间用逗号隔开

① 创建表时指定索引列

create table t_test_index4(
  id bigint primary key auto_increment,
  name varchar(20),
  sno varchar(10),
  class_id bigint,
  index(sno,class_id) # 复合主键
);

此时索引名默认是第一个键的列名

② 修改表中的列为复合索引

create table t_test_index5(
  id bigint primary key auto_increment,
  name varchar(20),
  sno varchar(10),
  class_id bigint
);
alter table t_test_index5 add index(sno,class_id);

③ 单独创建索引并指定索引名

create table t_test_index6(
  id bigint primary key auto_increment,
  name varchar(20),
  sno varchar(10),
  class_id bigint
);
create index index_name on t_test_index6(sno,class_id);

6.删除索引

① 删除主键索引

语法 : alter table 表名 drop primary key;

注意 : 如果主键是自增列 , 需要先改为非自增 , 再删去主键

示例 :

alter table t_test_index6 modify id bigint;
alter table t_test_index6 drop primary key;

② 其他索引

语法 : alter table 表名 drop index 索引名;

示例 :

alter table t_test_index6 drop index index_name;

7.创建索引注意事项

8.如何查看自己写的 SQL 走没走索引?

可以查看执行计划 , explain+查询语句

到此这篇关于MySQL数据库页与索引示例详解的文章就介绍到这了,更多相关mysql页和索引内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文