MySQL的索引

(1)索引概述

索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

索引的优点:

提高数据检索的效率,降低数据库的IO成本,通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。

索引的劣势:

索引列也是要占用空间的,索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE时,效率也降低。

(2)索引结构

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:

B+Tree索引:最常见的索引类型,大部分引擎都支持B+Tree索引

Hash索引:底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询

R-tree(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少。

Full-text(全文索引):是一种通过建立倒排索引,快速匹配文档的方式。

二叉树缺点:顺序插入时,会形成一个链表,查询性能大大降低,大数据量情况下,层级较深,检索速度慢;

红黑树:大数据量情况下,层级较深,检索速度慢。

B-Tree(多路平衡查找树):以一颗最大度数(max-degree)为5(5阶)的B-Tree为例(每个节点最多存储4个key,5个指针)

B-Tree的演变过程

B-Tree的演变过程: https://www.cs.usfca.edu/~galles/visualization/BTree.html

B+Tree:所有的元素都会存放在叶子节点;叶子节点形成一个单向链表;非叶子节点只起到索引的作用。

以一颗最大度数(max-degree)为4(4阶)的B+Tree为例

MySQL的B+Tree结构

MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。

MySQL中,页的默认大小时16KB。

为什么InnoDB存储引擎选择使用B+Tree索引结构

(a)相对于二叉树,层级更少,搜索效率高;

(b)对于B-Tree,无论是叶子节点还是非叶子节点,都会保存数据,

这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量

数据,只能增加树的高度,导致性能降低。

(c)相对Hash索引,B+Tree支持范围匹配和顺序操作。

(3)索引分类

主键索引:针对于表中主键创建的索引,默认自动创建,只能有一个;关键字:PRIMARY

唯一索引:避免同一个表中某数据列中的值重复,可以有多个;关键字:UNIQUE

常规索引:快速定位特定数据,可以有多个;

全文索引:全文索引查找的是文本中的关键词,而不是比较索引中的值,可以有多个。 关键字:FULLTEXT

在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:

聚集索引(Clustered Index)将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。必须有,而且只有一个。

二级索引(Secondary Index)将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键。可以存在多个。

聚集索引的选取规则:

(a)如果存在主键,主键索引就是聚集索引。

(b)如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。

(c)如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

聚集索引的叶子节点保存的是行数据。

(a)以下SQL语句,哪个执行效率高

select * from user where id=10;

select * from user where name='Arm';

备注 id为主键,name字段创建的有索引;

(b)InnoDB主键索引的B+Tree高度为多高呢?

假设:一行数据大小为1k,一页中可以存储16行这样的数据,InnoDB的指针占用6个字节的空间,主键即使为bigint,占用字节数为8。

假设高度为2:

n*8+(n+1)*6=16*1024, 算出n约为1170; 所以有1171个指针;

可以存储的行数为: 1171 * 16 = 18736;

假设高度为3:

可以存储的行数为: 1171 * 1171 * 16 = 21939856

(4)索引语法

创建索引:

CREATE [UNIQUE | FULLTEXT] INDEX index_name ON table_name(index_col_name, ...);

查看索引:

SHOW INDEX FROM table_name;

删除索引:

DROP INDEX index_name ON table_name;

表tb_user结构及数据如下:

当前表中的索引:

  1. name字段为姓名字段,该字段的值可能会重复,为该字段创建索引。

create index idex_user_name on tb_user(name);

创建之后,查看表中的索引:show index from tb_user;

  1. phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。

create unique index idx_user_phone on tb_user(phone);

查看创建的索引 show index from tb_user;

  1. 为profession、age、status创建联合索引。

create index idx_pro_age_sta on tb_user(profession, age, status);

查看创建就的索引: show index from tb_user;

  1. 为email建立合适的索引来提升查询效率。

create index idx_user_email on tb_user(email);

查看创建的索引: show index from tb_user;

相关推荐
ZFSS4 小时前
Localization Translate API 集成与使用指南
java·服务器·数据库·人工智能·mysql·ai编程
东风破1375 小时前
达梦DMDRS搭建、以及DMDRS双向同步
数据库·oracle·dm达梦数据库
KaMeidebaby6 小时前
卡梅德生物技术快报|抗独特型抗体开发:半抗原检测技术瓶颈拆解,抗独特型抗体开发工程化实践
前端·数据库·人工智能·其他·百度·新浪微博
NiceCloud喜云6 小时前
Claude Files API 深入:从上传、复用到配额管理的工程化指南
android·java·数据库·人工智能·python·json·飞书
A XMan.7 小时前
域名Whois信息查询V2版API接入指南
数据库
heimeiyingwang7 小时前
【架构实战】可观测性体系:从监控到全链路追踪
网络·数据库·架构
网管NO.17 小时前
SQL 日期函数全套精讲!时间格式化、日期加减、年月日提取,做日报周报直接套用
数据库·sql
杨云龙UP7 小时前
Linux 根分区被日志吃满?一次 58G Broker 日志清理实战_2026-05-20
linux·运维·服务器·数据库·hdfs·apache
sdk大全8 小时前
Studio 3T for MongoDB 2025.13.0
数据库·mongodb
码农阿豪8 小时前
平替MongoDB:金仓多模数据库助力电子证照国产化实践
数据库·mongodb