⑩② 【MySQL索引】详解MySQL`索引`:结构、分类、性能分析、设计及使用规则。

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: ⑩② 【MySQL索引】详解MySQL`索引`:结构、分类、性能分析、设计及使用规则。


⑩② 【MySQL索引】


1. 索引

索引

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

  • 索引的优缺点?
  • 优势:
  • ⚪提高数据检索效率,降低数据库IO成本;
  • ⚪通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗;
  • 劣势:
  • ⚪索引列需要占用空间,比无索引结构占用的空间更大。
  • ⚪索引虽大大提高了查询效率,但与此同时却降低了更新表的速度,如对表进行INSERT \ UPDATE \ DELETE 时,效率降低。




2. 索引的结构

索引结构

  • MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构。

  • B+Tree索引:最常见的索引类型,大部分引擎都支持B+树索引。
  • Hash索引:底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询。
  • R-tree(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,只要用于地理空间数据类型,较少使用。
  • Full-text(全文索引):是一种通过建立倒排索引,快速匹配文档的方式。类似于ES(Elasticsearch)。



🚀B+树索引

B+Tree索引

  • 特征:
  • ①每个节点最多可存放4个元素,五个指针
  • 叶子节点形成链表,存储了树的所有元素
  • 指针指向当前元素区间内的元素
  • MySQL索引数据结构对经典的B+Tree进行了优化。在原本B+树的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。



🚀Hash索引

Hash索引

  • 哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。

  • 哈希碰撞问题
  • 如果出现两个或多个键值映射到同一个槽位上,也就是出现hash碰撞时,可以通过链表解决问题。

  • Hash索引特点
  • ① Hash索引只能用于对等比较(=、in),不支持范围查询(between、>、< …)
  • ②无法利用Hash索引完成排序操作
  • ③查询效率高,通常只需要一次检索就可以完成,效率通常要高于B+Tree索引

  • MySQL数据库中,支持hash索引的是Memory引擎,而InnoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。



🚀思考题

  • 为什么InnoDB存储引擎选择使用B+Tree索引结构?
  • ⚪相对于二叉树,层级更少,搜索效率更高;
  • ⚪对于BTree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,会导致性能下降
  • ⚪相对Hash索引,B+Tree索引支持范围匹配和排序操作;




3. 索引的分类

索引分类

  • ①主键索引 —— PRIMARY
  • ②唯一索引 —— UNIQUE
  • ③常规索引
  • ④全文索引 —— FULLTEXT


  • 在InnoDB存储引擎中,根据索引的存储形式,又可以分为两种
  • 聚集索引(Clustered Index):B+Tree叶子节点下挂载这一行的数据
  • ①如果存在主键,主键索引就是聚集索引。
  • ②如果不存在主键,将使用第一个唯一索引**(UNIQUE)作为聚集索引。**
  • ③如果表没有主键,也没有合适的唯一索引InnoDB自动生成一个rowid作为隐藏的聚集索引。
  • 二级索引(Secondary Index):B+Tree叶子节点下挂载这一行的id




4. 创建、查看、删除索引

索引操作

  • 🚀创建索引
-- 使用UNIQUE关键字,创建唯一索引
-- 使用FULLTEXT关键字,创建全文索引
-- 不指定上述两者,创建常规索引
CREATE [UNIQUE | FULLTEXT] INDEX 索引名 ON 表名(字段1,字段2...);

  • 🚀查看索引
SHOW INDEX FROM 表名;

  • 🚀删除索引
DROP INDEX 字段名 ON 表名;

-- 演示:
-- 操作的表tb_user
create table tb_user(
  id int primary key auto_increment comment '主键',
  name varchar(50) not null comment '用户名',
  phone varchar(11) not null comment '手机号',
  email varchar(100) comment '邮箱',
  profession varchar(11) comment '专业',
  age tinyint unsigned comment '年龄',
  gender char(1) comment '性别 , 1: 男, 2: 女',
  status char(1) comment '状态',
  createtime datetime comment '创建时间'
) comment '系统用户表';
-- 查询索引
show index from tb_user;
-- 查询所有,竖向显示
show index from tb_user \G;
-- 1.name字段为姓名字段,该字段的值可能会重复,为该字段创建索引。
create index idx_user_name on tb_user(name);
-- 2.phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。
create unique index idx_user_phone on tb_user(phone);
-- 3.为profession、age、status创建联合索引。
create index idx_user_pro_age_sta on tb_user(profession,age,status);
-- 4.为email建立合适的索引来提升查询效率。
create index idx_user_email on tb_user(email);
-- 删除索引idx_user_email
drop index idx_user_email on tb_user;




5. SQL性能分析

🚀SQL执行频率

SQL执行频率

  • MySQL客户端连接成功后,通过show [session | global] status命令可以提供服务器状态信息。还可以通过show global status like 'Com_______'命令,查看当前数据库的INSERT \ UPDATE \ DELETE \ SELECT的访问频次。

  • 🚀查看服务器状态信息
SHOW [SESSION | GLOBAL] STATUS;

  • 🚀查看当前数据库的INSERT \ UPDATE \ DELETE \ SELECT的访问频次
-- 模糊匹配中有七个下划线'_'
SHOW GLOBAL STATUS LIKE 'Com_______';



🚀慢查询日志

慢查询日志

  • 慢查询日志记录了所有执行事件超过指定参数long_query_time,单位:秒,默认10秒的所有SQL语句的日志。

  • 🚀MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件/etc/my.cnf中配置相应信息:
# /etc/my.cnf文件内:
#开启MySQL慢查询开关
slow_query_log=1
#设置慢日志的时间为2秒,SQL语句执行超过2秒,被视为慢查询,记录慢查询日志
long_query_time=2
# 修改MySQL配置文件/etc/my.cnf【Linux环境下】
vi /etc/my.cnf
# 1. 按i键进行编辑
# 2. 寻找合适位置,输入上文给出的配置信息
# 3. 按Esc键推出编辑,输入:wq并回车保存退出
# 重启mysql服务器
systemctl restart mysqld


  • 🚀查询慢查询日志是否开启
-- OFF代表关闭
-- ON表示开启
SHOW VARIABLES LIKE 'slow_query_log';


  • 🚀查看慢查询日志内容[Linux环境下]
# 慢查询日志保存在:/var/lib/mysql/localhost-slow.log 文件下
cat /var/lib/mysql/localhost-slow.log



🚀SQL性能分析

- profile详情

profile详情

  • show profiles能够在做SQL优化时帮助我们了解时间都耗费在哪里了,通过have_profiling参数,能够看到当前MySQL是否支持查看profile详情。

  • 🚀查看MySQL是否支持查看profile详情
select @@have_profiling;


  • 🚀开启profiling (默认profiling是关闭的,可使用set语句在session/global级别开启)
-- 查看profiling开关是否开启
select @@profiling;
-- 开启profiling
set profiling=1;


  • 🚀查看每一条SQL耗时基本情况
show profiles;


  • 🚀查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;


  • 🚀查看指定query_id的SQL语句各个阶段耗时以及CPU使用情况
show profile cpu for query query_id;


- explain执行计划

explain执行计划:

  • EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。

  • 🚀查看SELECT语句执行计划(直接在select语句前加上explain / desc)
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件;
-- 或
DESC SELECT 字段列表 FROM 表名 WHERE 条件;


  • EXPLAIN执行计划 各个字段含义:
  • id:select查询的序列号,表示查询中执行select子句或者是操作表的顺序(id相同则执行顺序从上到下 、id不同则**值越大越先执行 **)
  • select_type:表示select查询的类型,常见的有:SIMPLE(简单表,不使用表连接或子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(select / where 之后包含了子查询)…
  • type:表示连接类型,性能由好到差的连接类型为:NULL、system、const、eq_ref、ref、range、index、all。
  • possible_key:显示可能引用在这张表上的索引,一个或多个。
  • Key:实际使用的索引,如果为NULL,表示没有使用索引。
  • Key_len:表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。
  • rows:MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的。
  • filtered:表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。




6. 索引的使用规则

最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将部分失效(后面的字段索引失效)。


范围查询

联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。


索引列运算

不要再索引列上进行运算操作(max() avg() count()等),否则索引会失效


字符串不加引号

字符串类型字段使用时,若不加引号'',索引失效


模糊查询

如果仅仅是字符串尾部模糊匹配,索引不会失效。如果是字符串头部模糊匹配,索引失效。


使用or来连接条件

用or分割开的条件,如果or前的条件中的列有索引,而or后面的列中没有索引,那么涉及的索引都不会被用到。即or连接的条件都需建立索引才能使得索引生效


数据分布影响

如果MySQL评估使用索引比全表更慢,则不使用索引。


SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

  • use index():建议查询时使用指定索引
SELECT 字段列表 FROM 表名 [USE INDEX(索引名)] WHERE 条件;

  • ignore index():建议查询时忽略指定索引
SELECT 字段列表 FROM 表名 [IGNORE INDEX(索引名)] WHERE 条件;

  • force index():查询时强制使用指定索引
SELECT 字段列表 FROM 表名 [FORCE INDEX(索引名)] WHERE 条件;


覆盖索引

== 应当尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),从而减少 select * 的使用。 ==

  • explain查看查询计划时,最后一个字段Extra的显示:
  • using index condition:查找使用了索引,但是需要回表查询数据。
  • using where;using index:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据。

  • 思考题:

  • 答:为id、password字段创建联合索引,这样就实现了覆盖索引,且不需要回表查询,效率高。


前缀索引

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

  • 🚀选取部分前缀建立索引
CREATE INDEX 索引名 ON 表名(column(前缀长度));
  • 前缀长度:
  • 可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
-- 计算tb_user表 字段email 的选择性
select count(distinct email) / count(*) from tb_user;
-- 原本基础上,设置前缀长度为5,计算选择性
select count(distinct substring(email,1,5)) / count(*) from tb_user;


单列索引 和 联合索引

  • 单列索引:一个索引只包含单个列
  • 联合索引:一个索引包含了多个列
  • 在业务场景中,如果存在多个查询条件,考虑针对查询字段检索引时,建议建立联合索引,而非单列索引。




7. 索引设计原则

  • 1.针对于数据量较大,且查询比较频繁的表建立索引。
  • 2.针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
  • 3.尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  • 4.如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引
  • 5.尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
  • 6.要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
  • 7.如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。




相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
28天前
|
JSON 关系型数据库 MySQL
MySQL JSON数据存储结构与操作
通过本文的介绍,我们了解了MySQL中JSON数据类型的基本操作、常用JSON函数、以及如何通过索引和优化来提高查询性能。JSON数据类型为存储和操作结构化数据提供了灵活性和便利性,在现代数据库应用中具有广泛的应用前景。希望本文对您在MySQL中使用JSON数据类型有所帮助。
35 0
|
3月前
|
SQL 缓存 关系型数据库
MySQL高级篇——性能分析工具
MySQL的慢查询日志,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long-query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为 10,意思是运行10秒以上(不含10秒)的语句,认为是超出了我们的最大忍耐时间值。它的主要作用是,帮助我们发现那些执行时间特别长的 SOL 查询,并且有针对性地进行优化,从而提高系统的整体效率。当我们的数据库服务器发生阻塞、运行变慢的时候,检查一下慢查询日志,找到那些慢查询,对解决问题很有帮助。
MySQL高级篇——性能分析工具
|
3月前
|
关系型数据库 MySQL 数据库
MYSQL索引的分类与创建语法详解
理解并合理应用这些索引类型,能够有效提高MySQL数据库的性能和查询效率。每种索引类型都有其特定的优势,适当地使用它们可以为数据库操作带来显著的性能提升。
107 3
|
5月前
|
存储 SQL 关系型数据库
(四)MySQL之索引初识篇:索引机制、索引分类、索引使用与管理综述
本篇中就对MySQL的索引机制有了全面认知,从索引的由来,到索引概述、索引管理、索引分类、唯一/全文/联合/空间索引的创建与使用等内容,进行了全面概述。
194 0
|
5月前
|
SQL 存储 数据库
MySQL设计规约问题之性能分析工具如Sql explain、show profile和mysqlsla在数据库性能优化中有什么作用
MySQL设计规约问题之性能分析工具如Sql explain、show profile和mysqlsla在数据库性能优化中有什么作用
|
5月前
|
SQL 关系型数据库 MySQL
Mysql:如何自定义导出表结构
通过以上方法,你可以灵活地自定义导出MySQL中的表结构,以满足不同的需求和场景。在进行操作的时候要注意权限问题以及路径问题,确保MySQL用户有权限写入指定的文件路径。在执行导出任务之前,还应确保你对数据库及其内容有足够的了解,以避免不必要的数据丢失或损坏。
80 1
|
5月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用问题之要将MySQL同步到Doris,并设置整库同步,只变更库名、表名和表结构都不变,该如何设置
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6月前
|
存储 关系型数据库 MySQL
|
18天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
32 1