浅析MySQL-索引篇01
什么是索引?
索引是帮助存储引擎快速获取数据的一种数据结构,类似于数据的目录。
索引的分类
按数据结构分类:
MySQL 常见索引有 B+Tree 索引、HASH 索引、Full-Text 索引。
Innodb是MySQL5.5之后的默认存储引擎,B+Tree索引类型也是MySQL采用的最多索引类型。
在创建表时,InnoDB存储引擎会根据不同的场景选择不同的列作为索引:
- 如果有主键,默认会使用主键作为聚簇索引的索引键;
- 如果没有主键,就选择一个唯一列作为聚簇索引的索引键;
- 如果两个都没有,将自动生成一个隐式自增 id 列作为聚簇索引的索引键;
其他索引都属于二级索引或非聚簇索引。创建的主键索引和二级索引默认使用的都是B+tree索引。
按物理存储分类:
索引分为聚簇索引、非聚簇索引。
聚簇索引的B+tree的叶子节点存放的是实际数据,所有完整的数据记录都存放在聚簇索引的B+Tree的叶子节点里;
非聚簇索引的B+Tree的叶子节点存放的是主键值,不是实际数据记录
因此,在查询时使用了非聚簇索引,如果查询的数据字段能在非聚簇索引里查询到,那么就不需要回表,这个过程称作覆盖索引。如果查询的数据字段不在非聚簇索引中,就会先检索非聚簇索引,找到对应的叶子节点,获取到主键值后,然后在检索聚簇索引,就能查到数据了,这个过程就称作回表。
按字段特性分类:
索引分为主键索引、唯一索引、普通索引、前缀索引。
这里说明下前缀索引:
前缀索引指的是对字符类型(char、varchar)字段的前几个字符建立的索引,而不是在整个字段上建立索引。使用此类索引可以检索索引占用的存储空间,提升查询效率。
create index idx_name_prefix on tbl_user(name(3));
按字段个数分类:
分为单列索引、联合索引。
这里说明下联合索引,它就是将多个字段组合成一个索引。
索引的结构
比如在tb_user中添加idx_name_age(name,age)联合索引
CREATE INDEX idx_name_age ON tbl_user(name, age);
下图就是联合索引idx_name_age中B+Tree形式的大致结构:
从上面的图可以看出,联合索引的非叶子节点用两个字段的值作为B+Tree的key值。当在联合索引查询数据时,先按name字段比较,在name字段相同的情况下在按age字段比较。也就是说先按name字段进行排序,然后再name字段相同的情况再按age字段排序。
因此,使用联合索引时,就会存在最左匹配原则。如果查询条件不遵守「最左匹配原则」联合索引会失效,查询就无法利用到索引进行快速查询。
为什么选择B+Tree?
-
B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。
-
B+ 树有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让 B+ 树在插入、删除的效率都更高,比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化;
-
B+ 树叶子节点之间用链表连接了起来,有利于范围查询,而 B 树要实现范围查询,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。
索引的优化
下面举例说明几种常见的优化索引手段:
- 前缀索引优化;
- 覆盖索引优化;
- 主键索引最好是自增的;
- 防止索引失效;
前缀索引优化
使用某个字段中字符串的前几个字符串建立索引,为什么需要使用前缀来建立索引呢?
目前是为了减小索引字段大小,可以增加一个索引页中存储的索引值,有效提高索引的查询速度。因为会存在大字符串的字段作为索引,这个场景就适合使用前缀索引方式来减小索引项的大小
缺点:①order by无法使用前缀索引 ②无法把前缀索引用作覆盖索引
覆盖索引优化
指的是SQL中查询的所有字段,在索引B+Tree的叶子节点都能找得到,从非聚簇索引中查询得到记录,而不需要通过聚簇索引查询获得,避免了回表的操作。
主键索引是自增
建表的时候,我们一般把主键设置成自增,为什么这么做呢?
Innodb引擎中,以聚簇索引为例,数据存放在叶子节点中,也就是说,同一个叶子节点内的各个数据都是按主键顺序存放的,因此当有一条新数据要插入时,数据库会根据主键将其插入到对应的叶子节点中。
如果使用自增主键,那么每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有数据,当页写满,就会自动开辟一个新页。因为每次插入一条新纪录,都是追加操作,不需要重新移动数据,因此这种插入数据的方法效率非常高。
如果使用非自增主键,那么每次插入主键的索引值都是随机的,每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这将不得不移动其他数据来满足新数据的插入,甚至需要从一个页复制数据到另外一个页,这种情况我们称为 页分裂。页分裂可能会导致造成大量的内存碎片,导致索引节后不紧凑,影响查询效率。
索引最好设置为 NOT NULL
- 第一:索引列存在NULL就会导致优化器在做索引选择的时候更加复杂,难以优化。比如进行索引统计,count会省略之为NULL的行
- 第二: NULL是一个没有意义的值,但是它会占用物理空间,所以会带来存储空间的问题。如果表中存在允许为NULL的字段,那么行格式中至少会用1字节空间存储NULL值列表。
防止索引失效
对索引使用左或者左右模糊匹配
当我们使用左或者左右模糊匹配的时候,都会造成索引失效
select * from tbl_score where name like '%王';
select * from tbl_score where name like '%王%';
执行计划中的 type=ALL 就代表了全表扫描,而没有走索引。
如果查询的是右模糊的话,会走索引。
select * from tbl_score like '王%';
执行计划中的type=range表示走了索引扫描。
为什么 like 关键字左或者左右模糊匹配无法走索引呢?
因为索引结构是B+Tree,它是按照「索引值」有序排序存储的,只能根据前缀进行比较。
对索引使用函数
如果查询条件中对索引字段使用函数,就会导致索引失效。
select * from tbl_score where mod(score, 2) = 0;
执行计划中type=ALL,代表未走索引。
为什么对索引使用函数,就无法走索引了呢?
因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,因此肯定没法走索引。但是在8.0版本后,增加了函数索引。即可这对函数计算后的值建立索引,也就是说索引的值是函数计算后的值。
alter table tbl_score add key idx_score_mod ((mod(score,2)));
添加完后,执行计划如下:
对索引进行表达式计算
在查询条件中对索引进行表达式计算,也是无法走索引的。
select * from tbl_score where age + 2=10;
执行计划如下,type=ALL未走索引
修改查询方式
select * from tbl_score where age = 10 - 2;
执行计划如下,type=ref走了索引
对索引隐式类型转换
如果索引字段是字符串类型,但是在条件查询中,输入的参数是整型的话,你会在执行计划的结果发现这条语句会走全表扫描
在tbl_score中存在一个字段status 类型是varchar(4)
select * from tbl_score where status=1;
执行计划中,type=ALL未走索引。
修改方式:
select * from tbl_score where status='1';
执行计划中,type=ref表示已走索引。
联合索引非最左匹配
联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配
select * from tbl_score where score= 10;
执行计划中type=ALL未走索引。
为什么联合索引不遵循最左匹配原则就会失效?
在联合索引的情况下,数据是按照索引第一列排序,第一列数据相同时才会按照第二列排序。
也就是说,如果我们想使用联合索引中尽可能多的列,查询条件中的各个列必须是联合索引中从最左边开始连续的列。如果我们仅仅按照第二列搜索,肯定无法走索引
WHERE 子句中的 OR
在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效
但是or查询条件中都有字段都是索引字段,并不一定走索引。还需要看优化器怎么决定。
相关文章:

浅析MySQL-索引篇01
什么是索引? 索引是帮助存储引擎快速获取数据的一种数据结构,类似于数据的目录。 索引的分类 按数据结构分类: MySQL 常见索引有 BTree 索引、HASH 索引、Full-Text 索引。 Innodb是MySQL5.5之后的默认存储引擎,BTree索引类型也…...

2028年企业云存储支出翻倍,达到1280亿美元
根据Omdia的研究,到2028年,企业云存储支出将从去年的570亿美元翻一番以上,达到1280亿美元。该研究分析了基础设施即服务(IaaS)和平台即服务(PaaS)数据中心的收入,作为年度存储数据服…...

ActiViz中的颜色映射表vtkLookupTable
文章目录 一、简介二、VtkLookupTable的创建与初始化三、设置数据范围四、颜色映射设置五、不透明度设置六、自定义颜色映射七、 不连续性颜色映射八、 预设颜色映射方案九、可视化效果优化十、与其他VTK组件的整合十一、 动态调整映射表十二、保存和加载颜色映射表一、简介 V…...

【Spring AOP 源码解析前篇】什么是 AOP | 通知类型 | 切点表达式| AOP 如何使用
前言(关于源码航行) 在准备面试和学习的过程中,我阅读了还算多的源码,比如 JUC、Spring、MyBatis,收获了很多代码的设计思想,也对平时调用的 API 有了更深入的理解;但过多散乱的笔记给我的整理…...

Laravel HTTP客户端:网络请求的瑞士军刀
标题:Laravel HTTP客户端:网络请求的瑞士军刀 Laravel的HTTP客户端是一个功能强大的工具,它提供了一种简洁、直观的方式来发送HTTP请求。无论是与外部API集成,还是进行网络数据抓取,Laravel的HTTP客户端都能满足你的需…...

7月07日,每日信息差
第一、6 月份,北京、上海、广州和深圳的新建商品住宅成交量分别环比增加 21%、66%、48% 和 38%,均创年内新高 第二、2024 年世界人工智能大会上,上海向四家企业发放了首批无驾驶人智能网联汽车示范应用许可,这些企业可以在浦东部…...

ubuntu 网络常用命令
在Ubuntu中,有许多网络相关的常用命令。以下是一些主要命令及其用途: ifconfig:此命令用于显示和配置网络接口信息。你可以使用它来查看IP地址、子网掩码、广播地址等。 例如:ifconfig 注意:在新版本的Linux发行版中…...

Python28-7.4 独立成分分析ICA分离混合音频
独立成分分析(Independent Component Analysis,ICA)是一种统计与计算技术,主要用于信号分离,即从多种混合信号中提取出独立的信号源。ICA在处理盲源分离(Blind Source Separation,BSS࿰…...

Spring Boot与Okta的集成
Spring Boot与Okta的集成 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何在Spring Boot应用中集成Okta,实现身份认证和授权的功能…...

MVC(Model-View-Controller)模式
MVC(Model-View-Controller)模式三个主要组件:模型(Model),视图(View),和控制器(Controller): 模型(Model)&a…...

MuLan:模仿人类画家的多对象图像生成
在图像生成领域,处理包含多个对象及其空间关系、相对大小、重叠和属性绑定的复杂提示时,现有的文本到图像模型仍面临挑战:当文本提示中包含多个对象,并且这些对象之间存在特定的空间关系时,现有模型往往难以准确地捕捉…...

如何在Android中实现网络通信,如HttpURLConnection和HttpClient。
在Android开发中,网络通信是一个不可或缺的功能,它允许应用与服务器交换数据,实现丰富的功能。在实现网络通信时,HttpURLConnection和HttpClient是两种常用的方式。下面将从技术难点、面试官关注点、回答吸引力以及代码举例四个方…...

评价ChatGPT与强人工智能的未来
在人工智能领域,ChatGPT的出现无疑是一个里程碑事件。它不仅展示了自然语言处理技术的巨大进步,也引发了人们对于强人工智能(AGI)的无限遐想。本文将从多个角度评价ChatGPT,并探讨强人工智能距离我们还有多远。 ChatGP…...

【web前端HTML+CSS+JS】--- CSS学习笔记02
一、CSS(层叠样式表)介绍 1.优势 2.定义解释 如果有多个选择器共同作用的话,只有优先级最高那层样式决定最终的效果 二、无语义化标签 div和span:只起到描述的作用,不带任何样式 三、标签选择器 1.标签/元素选择器…...

linux 安装 ImageMagick 及 php imagick扩展
安装imagick扩展前必须安装ImageMagick 一、安装ImageMagick wget http://www.imagemagick.org/download/ImageMagick.tar.gz 上面如果报错(cannot verify download.imagemagick.org’s certificate)执行 sudo yum install -y ca-certificates tar zxv…...

秋招突击——7/5——复习{}——新作{跳跃游戏II、划分字母区间、数组中的第K个大的元素(模板题,重要)、前K个高频元素}
文章目录 引言正文贪心——45 跳跃游戏II个人实现参考实现 划分字母区间个人实现参考实现 数组中的第K个最大元素个人实现参考做法 前K个高频元素个人实现参考实现 总结 引言 今天就开始的蛮早的,现在是九点多,刚好开始做算法,今天有希望能够…...

【Linux】信号的处理
你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 信号的处理 1 信号的处理2 内核态 VS 用户态3 键盘输入数据的过程4 如何理解OS如何正常的运行5 如何进行信号捕捉信号处理的总结6 可重入函数volatile关…...

Python数据分析的数据导入和导出
在Python数据分析中,数据的导入和导出是非常关键的步骤。这些步骤通常涉及到将数据从外部文件(如CSV、Excel、数据库等)读入到Python程序中,以及将处理后的数据导出回外部文件或数据库。以下是一些常用的库和方法来实现这些操作。…...

【JAVA多线程】线程池概论
目录 1.概述 2.ThreadPoolExector 2.1.参数 2.2.新任务提交流程 2.3.拒绝策略 2.4.代码示例 1.概述 线程池的核心: 线程池的实现原理是个标准的生产消费者模型,调用方不停向线程池中写数据,线程池中的线程组不停从队列中取任务。 实现…...

java双亲委派机制
Java中的双亲委派机制(Parent Delegation Model)是一种类加载机制,它确保了类加载的安全性和一致性。该机制规定了类加载器在加载类时的顺序和方式,从而避免了重复加载和类冲突问题。 以下是一个简单的自定义类加载器的示例&#…...

记录第一次使用air热更新golang项目
下载 go install github.com/cosmtrek/airlatest 下载时提示: module declares its path as: github.com/air-verse/air but was required as: github.com/cosmtrek/air 此时,需要在go.mod中加上这么一句: replace github.com/cosmtrek/air &…...

Leetcode 3213. Construct String with Minimum Cost
Leetcode 3213. Construct String with Minimum Cost 1. 解题思路2. 代码实现 题目链接:3213. Construct String with Minimum Cost 1. 解题思路 这一题的话思路上还是比较直接的,就是一个trie树加一个动态规划,通过trie树来快速寻找每一个…...

python操作SQLite3数据库进行增删改查
python操作SQLite3数据库进行增删改查 1、创建SQLite3数据库 可以通过Navicat图形化软件来创建: 2、创建表 利用Navicat图形化软件来创建: 存储在 SQLite 数据库中的每个值(或是由数据库引擎所操作的值)都有一个以下的存储类型: NULL. 值是空值。 INTEGER. 值是有符…...

【电控笔记6.7】非最小相位系统
全通滤波器 [...

Day05-04-持续集成总结
Day05-04-持续集成总结 1. 持续集成2. 代码上线目标项目 1. 持续集成 git 基本使用, 拉取代码,上传代码,分支操作,tag标签 gitlab 用户 用户组 项目 , 备份,https,优化. jenkins 工具平台,运维核心, 自由风格工程,maven风格项目,流水线项目, 流水线(pipeline) mavenpom.xmlta…...

PyQt5动态热力图清空画布关闭ColorBar
PyQt5生成正弦波动态热力图清空画布关闭ColorBar 1、简介 生成随机正弦波,使用pyqtgraph展示出来,并且使用热力图展示不同频率的正弦波,使用不同的画布颜色显示热力图的变化。 使用python3.8 导入库: pip install matplotlib==3.7.5 pip install numpy==1.24.4 pip in…...

python爬虫入门(一)之HTTP请求和响应
一、爬虫的三个步骤(要学习的内容) 1、获取网页内容 (HTTP请求、Requests库) 2、解析网页内容 (HTML网页结构、Beautiful Soup库) 3、存储或分析数据 b站学习链接: 【【Python爬虫】爆肝两…...

华为OD机考题(HJ41 称砝码)
前言 经过前期的数据结构和算法学习,开始以OD机考题作为练习题,继续加强下熟练程度。有需要的可以同步练习下。 描述 现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ; 每种砝码对应的数量为 x1,x2,x3...xn 。现在要…...

Qt涂鸦板
Qt版本:Qt6 具体代码: 头文件 dialog.h #ifndef DIALOG_H #define DIALOG_H#include <QDialog>QT_BEGIN_NAMESPACE namespace Ui { class Dialog; } QT_END_NAMESPACEclass Dialog : public QDialog {Q_OBJECTpublic:Dialog(QWidget *parent n…...

C++_03
1、构造函数 1.1 什么是构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。 每次构造的是构造成员变量的初始化值,内存空间等。 构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不…...