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;

执行:

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

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
240 66
|
1月前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
170 9
|
3月前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
15天前
|
SQL 存储 关系型数据库
MySQL秘籍之索引与查询优化实战指南
最左前缀原则。不冗余原则。最大选择性原则。所谓前缀索引,说白了就是对文本的前几个字符建立索引(具体是几个字符在建立索引时去指定),比如以产品名称的前 10 位来建索引,这样建立起来的索引更小,查询效率更快!
77 22
 MySQL秘籍之索引与查询优化实战指南
|
16天前
|
存储 关系型数据库 MySQL
MySQL中为什么要使用索引合并(Index Merge)?
通过这些内容的详细介绍和实际案例分析,希望能帮助您深入理解索引合并及其在MySQL中的
68 10
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
79 18
|
29天前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
59 8
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
68 7
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
100 5
|
1月前
|
存储 关系型数据库 MySQL
Mysql索引:深入理解InnoDb聚集索引与MyisAm非聚集索引
通过本文的介绍,希望您能深入理解InnoDB聚集索引与MyISAM非聚集索引的概念、结构和应用场景,从而在实际工作中灵活运用这些知识,优化数据库性能。
142 7