MySQL 索引(下)

 🎉欢迎您来到我的MySQL基础复习专栏

☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹
✨博客主页:小小恶斯法克的博客
🎈该系列文章专栏:重拾MySQL-进阶篇
🍹文章作者技术和水平很有限,如果文中出现错误,希望大家能指正🙏
📜 感谢大家的关注! ❤️

目录

🚀索引分类

🚀聚集索引&二级索引

🚀索引语法


🚀引分类

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

分类

关键字

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

默认自动创建 , 只能有一个

不允许NULL值

PRIMARY KEY

唯一

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

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

UNIQUE

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

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

INDEX

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

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

FULLTEXT

🚀聚集索引&二级索引

在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;

执行:

  


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/637227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++轮子 · STL关联容器

上一篇文章中我们简单的介绍了一下STL中的序列容器和容器适配器,这篇文章中我们将重点介绍STL中的关联容器(最后四个在概念上应该不是关联容器,但是因为和前面的容器联系太紧密,统一放在这里讲解),主要内容包括: std::setstd::mapstd::multi_mapstd::multi_setstd::unor…

推荐新版AI智能聊天系统网站源码ChatGPT NineAi

Nine AI.ChatGPT是基于ChatGPT开发的一个人工智能技术驱动的自然语言处理工具,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,真正像人类一样来聊天交流,甚至能完成撰写邮件、视频脚本、文案、翻译、代…

GoZero微服务个人探究之路(七)添加中间件、自定义中间件

说在前面 官方已经自己实现了很多中间件,我们可以方便的直接使用,不用重复造轮子了 开启方式可以看官方文档 中间件 | go-zero Documentation 实现自定义的中间件 在业务逻辑中,我们需要实现自定义功能的中间件 ------这里我们以实现跨源…

Typescript的类型推导与联合类型

考虑以下 TypeScript 代码片段: function processInput(input: string | number): void {if (typeof input "string") {console.log(Input is a string: ${input.toUpperCase()});} else if (typeof input "number") {console.log(Input is …

Spring+SprinMVC+MyBatis配置方式简易模板

SpringSprinMVCMyBatis配置方式简易模板代码Demo GitHub访问 ssm-tpl-cfg 一、SQL数据准备 创建数据库test,执行下方SQL创建表ssm-tpl-cfg /*Navicat Premium Data TransferSource Server : 127.0.0.1Source Server Type : MySQLSource Server Versio…

Linux ---- 小玩具

目录 一、安装: 1、佛祖保佑,永不宕机,永无bug 2、小火车 3、艺术字和其它 天气预报 艺术字 4、会说话的小牦牛 5、其他趣味图片 我爱你 腻害 英雄联盟 帅 忍 龙 你是猪 福 好运连连 欢迎 加油 想你 忘不了你 我错了 你…

细说JavaScript事件处理(JavaScript事件处理详解)

js语言的一个特色和就是它的动态性,即一时间驱动的方式对用户输入作出反应而不需要依赖服务器端程序。事件是指人机交互的结果,如鼠标移动、点击按钮、在表单中输入数据或载入新的Web洁面等。 一、什么是事件 1、事件类型 1.1、事件源 1.2、事件处理…

Node.js Stream.pipeline() Method

Why Stream.pipeline 通过流我们可以将一大块数据拆分为一小部分一点一点的流动起来,而无需一次性全部读入,在 Linux 下我们可以通过 | 符号实现,类似的在 Nodejs 的 Stream 模块中同样也为我们提供了 pipe() 方法来实现。 未使用 Stream p…

Java开发安全之:Unreleased Resource: Streams需确保流得到释放

Overview java 中的函数 getResponseBytes() 有时无法成功释放由 getInputStream() 函数分配的系统资源。 Details 程序可能无法成功释放某一项系统资源。 在这种情况下,在某些程序路径上,所分配的资源未释放。 资源泄露至少有两种常见的原因&#xf…

Pyro —— Understanding how pyro works

目录 Simulation fields Inside the Pyro Solver Colliders Pressure projection Simulation fields Pyro是纯体积流体解算器,表示流体状态的数据存于各种标量场和矢量场;Smoke Object会创建这些场,且能可视化这些场; vel场&…

【JavaEE】网络原理:网络中的一些基本概念

目录 1. 网络通信基础 1.1 IP地址 1.2 端口号 1.3 认识协议 1.4 五元组 1.5 协议分层 什么是协议分层 分层的作用 OSI七层模型 TCP/IP五层(或四层)模型 网络设备所在分层 网络分层对应 封装和分用 1. 网络通信基础 1.1 IP地址 概念:IP地址…

Java设计模式之工厂方法模式详解

Java设计模式之工厂方法模式详解 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!在今天的篇章中,我们将深入探讨Java设计模式中的一种魔法,那…

C语言/c++指针详细讲解【超详细】【由浅入深】

指针用法简单介绍 指针,是内存单元的编号。 内存条分好多好多小单元,一个小单元有 8 位,可以存放 8 个 0 或 1;也就是说,内存的编号不是以位算的,而是以字节算的,不是一个 0 或 1 是一个编号&…

函数 - JS

基本语法 function 关键字;函数名,应简明扼要且具有描述性,没有函数名就是匿名函数;参数列表,个数≥0,小括号不能省略;函数体。 /* 基本语法 */ function 函数名(参数) { 函数体 }声明与调用 …

立体视觉几何(一)

1.什么是立体视觉几何 立体视觉对应重建: • 对应:给定一幅图像中的点pl,找到另一幅图像中的对应点pr。 • 重建:给定对应关系(pl, pr),计算空间中相应点的3D 坐标P。 立体视觉:从图像中的投影恢复场景中点…

list下

文章目录 注意:const迭代器怎么写?运用场合? inserterase析构函数赋值和拷贝构造区别?拷贝构造不能写那个swap,为什么?拷贝构造代码 面试问题什么是迭代器失效?vector、list的区别? 完整代码 注…

React16源码: React中的reconcileChildIterator和reconcileChildrenArray的源码实现

reconcileChildIterator 和 reconcileChildrenArray 1 )概述 在react更新某一个节点的时候,要根据这个节点,它的类型去获取它的children比如说如果是 Function Component,它要调用这个 component 计算出它的return的属性return的…

qt学习:QT对话框+颜色+文件+字体+输入

目录 概述 继承图 QColorDialog 颜色对话框 QFileDialog 文件对话框 保存文件对话框 QFontDialog 字体对话框 QInputDialog 输入对话框 概述 对于对话框的功能,在GUI图形界面开发过程,使用是非常多,那么Qt也提供了丰富的对话框类QDia…

网络:FTP

1. FTP 文件传输协议,FTP是用来传输文件的协议。使用FTP实现远程文件传输的同时,还可以保证数据传输的可靠性和高效性。 2. 特点 明文传输。 作用:可以从服务器上下载文件,或将本地文件上传到服务器。 3. FTP原理 FTP有控制层面…

坦克大战游戏代码

坦克大战游戏 主函数战场面板开始界面坦克父类敌方坦克我方坦克子弹爆炸效果数据存盘及恢复图片 主函数 package cn.wenxiao.release9;import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JFrame; import javax.swing.JMenu; impor…