MySQL进阶 索引

一、概述

索引是数据库中用于加速数据检索的数据结构,类似于书籍的目录。通过创建索引,可以显著减少查询时需要扫描的数据量,提高查询效率。MySQL支持多种索引类型,适用于不同的场景和需求。

二、索引结构

1、B+Tree

最常用的索引类型,适用于全值匹配、范围查询和前缀匹配。

下面以一颗最大度数为4的B+Tree为例

可以观察到,与BTree不同,B+Tree的数据全在叶子节点,非叶子节点只用于存储键值,不存储数据,因此节点更小。更适合磁盘存储。同样,因为数据都在叶子节点,查找每个数据所需要的时间相差不大,具有更稳定的性能。在MySQL中,对传统B+Tree的结构进行了优化,更利于查询,如下图

在原B+Tree的基础上,加上了一个指向邻向叶子节点的指针,形成了带有顺序指针的B+Tree,使区间访问的性能更佳。

2、哈希索引

基于哈希表实现,对于主键等值查询速度比B+Tree快,但因为其不支持范围查询,因此其泛用性相对于B+Tree不高。

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

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

(2)对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;

三、索引分类

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

聚集索引(根据id主键)

二级索引(根据name)

四、索引语法

1、创建索引

sql 复制代码
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name(index_col_name,...);

ON前的字段为构建的索引名,括号内的字段为构建的索引在当前数据库中的字段名。

2、查看索引

sql 复制代码
SHOW INDEX FROM table_name;

3、删除索引

sql 复制代码
DROP INDEX index_name ON table_name;

五、性能分析

1、SQL执行频率

为了辅助创建索引,MySQL提供了一些命令可以用于查询当前服务器的INSERT、DELETE、UPDATE、SELECT指令的执行频次

语法

sql 复制代码
SHOW [session|global] STATUS;

选择session为查询当前会话的执行频次,global为全局的执行频率。

2、慢查询日志

慢查询日志是记录了所有执行时间超过指定参数(long_query_time,单位秒,默认为10s)的所有SQL语句的日志。

MySQL的慢查询日志默认没有开启。需要在MySQL的配置文件配置以下信息(/etc/my.cnf)

慢查询日志的位置位于/var/lib/mysql/localhost-slow.log文件下,注意,这里是本地虚拟机下的文件名,若在服务器中localhost会变为该服务器ip。

3、show profiles命令

show profiles命令可以帮助我们在做SQL优化时了解时间都耗费到哪个位置了。

通过have_profiling参数,可以知道当前数据库是否支持此操作。

若为NO,可以通过set profiling=1指令开启。

具体指令

show profiles可以获取当前会话执行的所有sql并展示其耗时情况,每条sql都有对应id,用于后两个指令。

4、explain执行计划

explain执行计划是构建索引时常用的指令。这个指令可以获取到MySQL如何执行SELECT语句的信息。

explain执行计划各字段含义

六、索引使用

假设目前有一张学生表,有id,name,course,age,grade,字段

sql 复制代码
SELECT * FROM student WHERE name='张三';

如果该表内有1000万条数据,执行此查询语句可能需要20s。

sql 复制代码
CREATE INDEX idx_student_name on student(name);

执行该语句为name构建索引后,再次执行该SELECT语句,我们能观察到时间已经压缩到了几毫秒。

此时使用的为单列索引。

如果使用的是联合索引,则需要遵守最左前缀原则。

*最左前缀法则:查询从索引的最左列开始(构建联合索引时括号内的第一个字段必须存在),并且不跳过索引中的列。

如果跳过某一列,索引将部分失效(跳过的那一列后面的索引都失效),所以构建联合索引时,需要注意括号内字段的顺序。

例:

sql 复制代码
CREATE INDEX idx_student_name_age_coruse on student(name,age,course);
sql 复制代码
SELECT * FROM student where age = 1 AND course = '20260101';

此次SELECT语句就没有使用到索引,因为构建索引时最左边的字段name没有出现。where语句后字段出现的顺序不重要,但最左字段必须出现。

*索引列上不能出现运算操作,否则索引失效。例如substring(name,10)等操作。

*用or分割开的条件,如果or前的条件有索引,而后面的列没有索引,那么涉及的索引都不会使用。

*SQL提示语法

SQL提示就是在SQL语句中加入一些人为的提示起到优化操作的目的。

where中使用了>或<符号会导致此处和此处后字段的索引失效,所以尽量使用>=或<=来筛选数据。

⭐覆盖索引&回表查询

查询时尽量不使用 * 作为条件,回顾上图

此处构建了name的单列索引,此时通过name查询能获取name和id的值,若是查询条件中含有这两个之外的字段,就会发生回表查询,即通过获取的id值在聚集索引中获取一整行(row)的值,然后再输出。直接在索引建的二级索引中获取查询条件中的所有数据的查询方法叫覆盖查询。

不止单索引可以触发覆盖查询,联合索引也行,因此在建立索引时尽量使用联合索引,配合覆盖查询使用,可以大大提升查询效率。

尽量使用覆盖查询(查询使用了索引,并且所需要返回的列在该索引中能够全部找到)。

⭐前缀索引

当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

语法

sql 复制代码
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name(index_col_name(n),...);

括号内的n为需要截取的前缀长度。

n值可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

例如 course 中n为5时的选择性

sql 复制代码
SELECT count(distinct substring(course,5))/count(*) from student;

多条件联合查询时,MySQL优化器会根据使用哪个索引的效率更高选择使用的索引。

七、索引的设计原则

1.针对于数据量较大,且查询比较频繁的表建立索引。

2.针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。

  1. 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。

  2. 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。

  3. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。

  4. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。

  5. 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

相关推荐
未来之窗软件服务2 小时前
数据库优化提速(四)数据库数据批量补齐—仙盟创梦IDE
数据库·数据库调优·仙盟创梦ide·东方仙盟
optimistic_chen2 小时前
【Redis系列】分布式锁
linux·数据库·redis·分布式·缓存
xuekai200809012 小时前
GaussDB-SQL优化案例
数据库·sql·gaussdb
老邓计算机毕设2 小时前
SSM养老院管理系统的设计于实现78fyn(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·计算机毕业设计·养老院管理系统·ssm 框架
a程序小傲3 小时前
京东Java面试被问:基于Gossip协议的最终一致性实现和收敛时间
java·开发语言·前端·数据库·python·面试·状态模式
重生之绝世牛码3 小时前
Linux软件安装 —— PostgreSQL集群安装(主从复制集群)
大数据·linux·运维·数据库·postgresql·软件安装·postgresql主从集群
程序员小白条3 小时前
面试 Java 基础八股文十问十答第二十二期
java·开发语言·数据库·面试·职场和发展·毕设
万象.3 小时前
redis客户端安装与实现C++版本
数据库·c++·redis
Yiyaoshujuku3 小时前
疾病的发病率、发病人数、患病率、患病人数、死亡率、死亡人数查询网站及数据库
数据库·人工智能·算法