MySQL 索引(下)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL 索引(下)

🚀引分类

在MySQL数据库将索引的具体类型主要分为以下几类主键索引唯一索引常规索引文索引

分类

关键字

针对于表中主键创建的索引,唯一标识表中的每一行数据

默认自动创建 只能有一个

不允许NULL值

PRIMARY KEY

唯一

避免同一个表中某数据列中的值重复,确保列中的值唯一

可以有多个NULL值
允许重复值,但不允许重复的索引值

UNIQUE

快速定位特定数据,提高查询性能

- 允许重复值和NULL值
- 适用于经常被搜索的列

INDEX

全文索引查找的是文本中的关键词而不是比较索引中的值

只能在MyISAM存储引擎上使用
适用于大量文本数据的搜索

🚀聚集索引&二级索引

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

分类

集索引 (Clustered

 

Index)

将数据存储与索引放到了一块索引结构的叶子 节点保存了行数据

须有,而且只 有一个

二级索引(Secondary Index)

将数据与索引分开存储索引结构的叶子节点关 联的是对应的主键

可以存在多个

聚集索引选取规则 :

✨表中只能有一个聚集索引:每个表只能有一个聚集索引,该索引决定了数据在磁盘上的物理排序顺序。

✨主键作为默认的聚集索引:如果没有显式地指定聚集索引,MySQL将使用主键作为默认的聚集索引。主键是唯一标识表中每一行数据的列。(即如果存在主键,主键索引就是聚集索引。)

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

✨唯一非空索引可以作为聚集索引:如果表中没有主键或者不想使用主键作为聚集索引,可以选择一个唯一非空索引作为聚集索引,这样可以提高查询性能并减少磁盘IO操作。

聚集索引的选择应考虑查询频率和范围:选择适合查询频率高且范围较小的列作为聚集索引,这样可以减少磁盘IO操作,并提高查询效率。

✨聚集索引的列顺序很重要:聚集索引的列顺序对查询性能有影响,通常情况下,将经常用于过滤和排序的列放在前面,以便优化查询性能。

✨避免频繁更新聚集索引列:由于聚集索引决定了数据在磁盘上的物理排序顺序,频繁更新聚集索引列可能导致数据重组和性能下降,因此,如果有大量更新操作,应该谨慎选择聚集索引。

✨请注意,聚集索引只适用于使用InnoDB存储引擎的表。对于使用MyISAM存储引擎的表,可以通过显示指定ALTER TABLE语句来创建聚集索引。

聚集索引和二级索引的具体结构如下:(以下分析以及图片来自于黑马的视频)  


聚集索引的叶子节点下挂的是这一列的数据  

二级索引的叶子节点下挂的是该字段值对应的主键值

接下来我们来分析一下当我们执行如下的SQL语句时具体的查找过程是什么样子的

具体过程如下 :

① . 由于是根据name字段进行查询,所以先根据name='Arm'到name字段的二级索引中进行匹配查找,但是在二级索引中只能查找到Arm对应的主键值10。

② . 由于查询返回的数据是*,所以此时,还需要根据主键值10,到聚集索引中查找10对应的记录,最终找到10对应的行row。

③ . 最终拿到这一行的数据,直接返回即可。

回表查询: 这种先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取数据的方式,就称之为回表查询。

✨以下两条SQL语句,那个执行效率高? 为什么?

A. select * from user where id = 5 ;

B. select * from user where name = 'bob' ;

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

解答

✨在这种情况下,执行效率高的SQL语句是A. select * from user where id = 5;。原因如下:

✨主键索引的查找效率高:由于id是主键,主键索引是一种特殊的索引,具有唯一性和快速查找的特点。通过主键索引可以直接定位到指定id的行,因此查询效率高。

✨因为A语句直接走聚集索引,直接返回数据。  

✨而B语句需要先查询name字段的二级索引,然后再查询聚集索引,也就是需要进行回表查询。

思考

InnoDB主键索引的B+tree高度为多高呢 ?

InnoDB主键索引的B+树的高度取决于数据表中的行数和索引的大小

B+树是一种常用的索引结构,用于在数据库中实现索引。对于InnoDB存储引擎而言,主键索引是基于B+树实现的。

B+树的高度是指从根节点到叶子节点的层数。在InnoDB中,B+树的高度通常较低,这是因为InnoDB采用了多级索引的技术。


假设 :

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

高度为2:

n * 8 + (n + 1) * 6 = 16*1024 , 算出n约为  1170

1171* 16 = 18736

也就是说,如果树的高度为2,则可以存储  18000 多条记录。

高度为3:

1171 * 1171 * 16 = 21939856

也就是说,如果树的高度为3,则可以存储  2200w 左右的记录

🚀索引语法

创建索引

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

查看索引

SHOW  INDEX  FROM  table_name ;

删除索引

DROP  INDEX  index_name  ON  table_name ;

案例演示 :

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 '用户表 ';
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'a ', '15377777770 ', 'lvbu666@163.com', '软件工程 ', 23, '1 ', '6 ', '2001-02-02 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'b ', '15377777771 ', 'caocao666@qq.com', '电气工程 ', 33, '1 ', '0 ', '2001-03-05 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'c ', '15377777772 ', '17799990@139.com', '计科 ', 34, '1 ', '2 ', '2002-03-02 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'd ', '15377777773 ', '17799990@sina.com', '工程造价 ', 54, '1 ', '0 ', '2001-07-02 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'e ', '15377777774 ', '19980729@sina.com', '软件工程 ', 23, '2 ', '1 ', '2001-04-22 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'f ', '15377777775 ', 'daqiao666@sina.com', '药学 ', 22, '2 ', '0 ', '2001-02-07 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'g ', '15377777776 ', 'luna_love@sina.com', '应用数学 ', 24, '2 ', '0 ', '2001-02-08 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'h ', '17799990007 ', 'chengyaojin@163.com', '化工 ', 38, '1 ', '5 ', '2001-05-23 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'i ', '17799990008 ', 'xiaoyu666@qq.com', '金属材料 ', 43, '1 ', '0 ', '2001-09-18 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'j ', '17799990009 ', 'baiqi666@sina.com', '机械工程及其自动 化 ', 27, '1 ', '2 ', '2001-08-16 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'k ', '17799990010 ', 'hanxin520@163.com', '无机非金属材料工 程 ', 27, '1 ', '0 ', '2001-06-12 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'l ', '17799990011 ', 'jingke123@163.com', '会计 ', 29, '1 ', '0 ', '2001-05-11 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'n ', '17799990012 ', 'lanlinwang666@126.com', '工程造价 ', 44, '1 ', '1 ', '2001-04-09 00:00:00 ');
INSERT INTO tb_user (name, phone, email, profession, age, gender, status,
createtime) VALUES ( 'm ', '17799990013 ', 'kuangtie@sina.com', '应用数学 ', 43, '1 ', '2 ', '2001-04-10 00:00:00 ');

数据如下:


完成下列需求:

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

CREATE INDEX idx_user_name ON tb_user (name);

如果name字段的值可能会重复,可以使用普通索引来提高查询效率。可以使用以下SQL语句为name字段创建普通索引:

ALTER TABLE tb_user ADD INDEX idx_name (name);

这条语句使用了ALTER TABLE命令,用于修改表结构。ADD INDEX表示要添加一个普通索引,idx_name是索引的名称,name是要创建索引的字段名。

执行这条语句后,MySQL会为name字段创建一个普通索引,可以提高对该字段的查询效率。当查询条件中包含name字段时,MySQL可以使用该索引进行快速查询。需要注意的是,如果name字段的值经常被更新,那么维护索引的代价可能会比较高,因此需要根据实际情况来选择是否创建索引。

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

create index idx_user_phone on tb_user (phone);
ALTER TABLE tb_user ADD UNIQUE INDEX idx_phone (phone);

这条语句使用了ALTER TABLE命令,用于修改表结构。ADD UNIQUE INDEX表示要添加一个唯一索引,idx_phone是索引的名称,phone是要创建唯一索引的字段名。

执行这条语句后,MySQL会为phone字段创建一个唯一索引,确保该字段的值非空且唯一。如果插入重复的phone值,MySQL会抛出错误提示。

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

CREATE INDEX idx_profession_age_status ON tb_user (profession, age, status);
ALTER TABLE tb_user ADD INDEX idx_profession_age_status (profession, age, status);

这条语句使用了ALTER TABLE命令,用于修改表结构。ADD INDEX表示要添加一个普通索引,idx_profession_age_status是索引的名称,profession、age、status是要创建联合索引的字段名。

执行这条语句后,MySQL会为profession、age、status字段创建一个联合索引,可以提高这三个字段的查询效率。当查询条件中包含这三个字段中的任意一个或多个时,MySQL可以使用该联合索引进行快速查询。

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

CREATE INDEX idx_email ON tb_user (email);

为了提高email字段的查询效率,可以根据实际情况选择创建普通索引或全文索引。

如果查询条件中只包含email字段,可以使用普通索引。可以使用以下SQL语句为email字段创建普通索引:

ALTER TABLE tb_user ADD INDEX idx_email (email);

这条语句使用了ALTER TABLE命令,用于修改表结构。ADD INDEX表示要添加一个普通索引,idx_email是索引的名称,email是要创建索引的字段名。

如果查询条件中包含email字段的全文搜索,可以使用全文索引。可以使用以下SQL语句为email字段创建全文索引:

ALTER TABLE tb_user ADD FULLTEXT INDEX idx_email (email);

这条语句使用了ALTER TABLE命令,用于修改表结构。ADD FULLTEXT INDEX表示要添加一个全文索引,idx_email是索引的名称,email是要创建索引的字段名。

需要注意的是,全文索引只能用于全文搜索,不能用于普通的等值查询。因此,如果查询条件中只包含email字段的等值查询,应该使用普通索引。

完成上述的需求之后,我们再查看tb_user表的所有的索引数据。

show index from tb_user;

执行:

今天的学习就到这里,希望对你有帮助!

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
16天前
|
存储 NoSQL 关系型数据库
为什么MySQL不使用红黑树做索引
本文详细探讨了MySQL索引机制,解释了为何添加索引能提升查询效率。索引如同数据库的“目录”,在数据量庞大时提高查询速度。文中介绍了常见索引数据结构:哈希表、有序数组和搜索树(包括二叉树、平衡二叉树、红黑树、B-树和B+树)。重点分析了B+树在MyISAM和InnoDB引擎中的应用,并讨论了聚簇索引、非聚簇索引、联合索引及最左前缀原则。最后,还介绍了LSM-Tree在高频写入场景下的优势。通过对比多种数据结构,帮助理解不同场景下的索引选择。
51 6
|
13天前
|
SQL 关系型数据库 MySQL
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
|
7天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
38 3
Mysql(4)—数据库索引
|
20小时前
|
存储 关系型数据库 MySQL
如何在MySQL中进行索引的创建和管理?
【10月更文挑战第16天】如何在MySQL中进行索引的创建和管理?
10 1
|
1月前
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
396 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
16天前
|
监控 关系型数据库 MySQL
MySQL数据表索引命名规范
MySQL数据表索引命名规范
26 1
|
16天前
|
存储 SQL 关系型数据库
mysql中主键索引和联合索引的原理与区别
本文详细介绍了MySQL中的主键索引和联合索引原理及其区别。主键索引按主键值排序,叶节点仅存储数据区,而索引页则存储索引和指向数据域的指针。联合索引由多个字段组成,遵循最左前缀原则,可提高查询效率。文章还探讨了索引扫描原理、索引失效情况及设计原则,并对比了InnoDB与MyISAM存储引擎中聚簇索引和非聚簇索引的特点。对于优化MySQL性能具有参考价值。
|
22天前
|
存储 关系型数据库 MySQL
MySQL中的索引及怎么使用
综上所述,MySQL索引的正确使用是数据库性能调优的关键一环。通过合理设计索引结构,结合业务需求和数据特性,可以有效提升数据库查询响应速度,降低系统资源消耗,从而确保应用的高效运行。
49 1
|
2天前
|
监控 关系型数据库 MySQL
mysql8索引优化
综上所述,深入理解和有效实施这些索引优化策略,是解锁MySQL 8.0数据库高性能查询的关键。
9 0
|
1月前
|
关系型数据库 MySQL 数据库
MySQL删除全局唯一索引unique
这篇文章介绍了如何在MySQL数据库中删除全局唯一的索引(unique index),包括查看索引、删除索引的方法和确认删除后的状态。
64 9