Mysql的索引详解
零. 索引类型概述
1. 实际开发中使用的索引种类
- 主键索引
- 唯一索引
- 普通索引
- 联合索引
- 全文索引
- 空间索引
2. 索引的格式类型
- BTree类型
- Hash类型
- FullText类型(全文索引)
- RTree类型(空间索引)
MySQL
的索引方法,主要包括BTREE
和HASH
。
顾名思义,BTREE
方法,就是通过构建B+
树的方法来组织索引结构;而HASH
方法,就是通过构建哈希表的方法来组织索引结构。
3. 以索引数据存储方式划分
- 聚集索引
- 非聚集索引
4. 以技巧划分
- 覆盖索引
- 前缀索引
也有人把聚集索引叫做聚簇索引
一、索引介绍
索引是一种数据结构,索引的作用主要是为了提高检索效率,添加一个索引需要选择一个字段作为索引依据
索引数据格式主要有两种
- Hash
- B+Tree
在实际开发中,其实用的最多的是B+Tree数据类型,因为hash数据格式是不支持范围查询的,而基于二叉树数据结构的B+Tree可以支持范围查询(注:B+Tree是B树的进化版)
拓展
(1)Mysql索引为什么使用B+Tree数据结构?
从计算机原理出发,是因为索引本身消耗就很大,不可能全部储存到内存中,因此索引往往索引文件的形式存储在磁盘上,那这样话,磁盘IO效率就会起决定性的作用。
(2)全文索引和空间索引是什么?
二、索引类型
1、普通索引
普通索引是最基本的索引,也是最常用的索引,创建只是为了提高查询效率,值可以为空,没有任何限制
alter table 表名 add index 索引名(添加索引的字段)
2、唯一索引
唯一索引和普通索引类似,值也可以为空,唯一区别是添加的字段是唯一性,列值不允许重复
alter table 表名 add unique 索引名(添加索引的字段)
3、主键索引
主键索引是一种特殊的唯一索引, 值不允许为空 和 列值不允许重复,且一张表只允许有一个主键索引
alter table 表名 add primary key (添加索引的字段)
4、联合索引
联合索引,顾名思义,就是多个索引联合在一起组成的一种索引类型。
//索引名可以是index_xx_xx
alter table 表名 add index 索引名(索引1,索引2,索引3)
5. 关于联合索引的拓展
(1)最左前缀匹配原则
建立联合索引时会遵循最左匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配
例如🌰
在user表中为 name、address、phone 三个字段添加联合索引
ALTER TABLE user ADD INDEX index_three(name,address,phoen)
下面三条sql语句都能命中索引
SELCET * FROM user WHERE address =’ 北京’ AND phone = ‘12345’ AND name = ‘张三’;SELCET * FROM user WHERE name = ‘张三’ AND address = ‘北京’;SELCET * FROM user WHERE name = ‘张三’;
这三条sql语句都会匹配联合索引,按顺序是 (name,address,phone) 、(name,address) 、(name),其实使用联合索引时可以不用按照建索引时候的顺序,如使用and条件,因为执行sql语句时,MYSQL的优化器会自动帮我们调整where条件中的顺序,但是,使用联合索引必须使用建索引的第一个字段name,即最左边的字段,否则索引无效,如下:
SELCET * FROM user WHERE address = ‘北京’;SELCET * FROM user WHERE address = ‘北京’’ AND phone = ‘12345’ ;
以上联合索引都会失效,可以总结一句话:用到最左边的字段,就算成功
(2)联合主键索引
上面说到了主键索引,其实主键也可以由多个字段组成
🌰借丁奇大佬的例子
DBA 小吕在入职新公司的时候,就发现自己接手维护的库里面,有这么一个表,表结构定义类似这样的:
CREATE TABLE `user` ('a' int(11) NOT NULL,'b' int(11) NOT NULL,'c' int(11) NOT NULL,'d' int(11) NOT NULL,PRIMARY KEY ('a','b'),KEY 'c' ('c'),KEY 'ca' ('c','a'),KEY 'cb' ('c','b')
) ENGINE=InnoDB;
公司的同事告诉他说,由于历史原因,这个表需要 a、b 做联合主键,这个小吕理解了。但是,学过本章内容的小吕又纳闷了,既然主键包含了 a、b 这两个字段,那意味着单独在字段 c 上创建一个索引,就已经包含了三个字段了呀,为什么要创建“ca”、“cb”这两个索引?同事告诉他,是因为他们的业务里面有这样的两种语句:
select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;
对于一般不太了解索引数据结构的人来说,会觉得上面的建的索引是没有问题的,但实际上面有一个错误,索引 “ca” 是多余的。
这是为什么?查询 where c = N order by a 难道不需要 “ca” 索引吗?
答案是需要的,不过需要明白的是,索引C是普通索引,C索引树上存放的是联合主键 (ab)的值,所以C索引树叶节点存放的值是(cab),根据最左前缀原则,就没必要再建(ca)索引了。但是(cb)索引还是需要的,在cb索引中,实际上是(cba)。
使用到了最左前缀原则和聚集索引相关的知识点
三、聚集索引和非聚集索引
1、非聚集索引
索引和表数据分开存储,就是非聚集索引(也有叫二级索引或辅助索引)。
非聚集索引一般就是指MyIsam引擎的索引,因为MyIsam引擎的索引和数据是分开储存的,如下图显示,MyIsam的索引B+Tree下data域储存的是数据地址,每次查询索引时,都是先从索引树上获取数据地址,在通过地址获取对应的数据 。所以,MyIsam表会有三个文件,分别是索引文件、表结构文件、数据文件。
2、聚集索引
索引和表数据存储在一起,就是聚集索引。
以InnoDB引擎举例,InnoDB引擎的主键是和表数据存储在一起,每个树节点储存每行一行的数据。如果有看过InnoDB引擎的表文件,就会发现,其实InnoDB表数据文件就是主索引文件,如下图的Innodb表数据二叉树显示,B+Tree数结构的主键索引,每个树节点主键下的data域,都是存放对应该主键的行数据。所以,InnoBD表数据文件本身就是一个B+树文件。InnoBD表一共有两个文件,分别是索引文件、表结构文件。
需要注意,InnoDB引擎除了主键索引,其他的索引的data域都是存主键索引的值,使用辅助查询时,是先通过辅助索引获取到主键,在通过主键获取主键索引B+树里的data域里的数据。总结:Innodb引擎表主键索引树叶节点存储:每行的数据;辅助索引树叶节点存的是:字段值和主键值。
3、实际开发聚集索引的不同
🌰先建个Innodb引擎的user表,表中有两个索引,一个是主键索引(聚集索引)ID,和另一个普通索引(非聚集索引)index_cardId 身份证ID
CREATE TABLE `user` ( `ID` INT NOT NULL AUTO_INCREMENT, `cardId` VARCHAR(50) NOT NULL, `name` VARCHAR(20) NOT NULL,`age` VARCHAR(10) NOT NULL,PRIMARY KEY (`ID`),KEY 'index_cardId' ('cardId') USING BTREE
)engine=InnoDB;
假如有一条语句:
SELECT * FROM user WHERE ID = 100;
即用主键的查询方式,搜索了ID这个索引的B+树,只需直接从这颗B+树中找到对应的ID获取到对应行的数据就可以。
如果用 index_cardId 普通索引查询:
SELECT * FROM user WHERE cardId = ‘43212341234’;
则需要搜索可 index_cardId 这个索引树,从index_cardId 这颗索引树上获取到主键索引的值,在通过值从主键索引的B+树上获取对应的数据,也就是说,非主键索引的查询需要多扫描了一棵索引树,这个过程我们称为回表
所以,在实际开发中,我们应尽量使用主键查询
四、覆盖索引
首先要明白,索引的使用过程,假如查询一条sql语句:
select col1 from test where col1=1;
假如test表有1000W条数据,在col1字段建了一个普通索引,然后sql查询时,会通过col1索引筛选出符合条件的200W条数据,而且能在col1索引上获取col1字段的数据,无需回表查询,直接返回,这就是覆盖索引。
反之,如果在上面的sql语句查询的字段在加一个col2字段
select col1,col2 from test where col1=1;
即使col1索引获取col1字段的值,但是因为没有col2字段的值,所以还需要回表查询,再获取200W条数据字段col2的值,才返回。那这样就不是覆盖索引了。
实际开发中覆盖索引的价值
实际开发中,优化查询的时候是否回表,是优化的重要目标,所以使用索引的时候,应该尽量使sql语句可以从索引中获取到需要的数据,例如上面的例子,可以增加col2字段的索引,这样就可以避免回表查询。
但是,如果查询的字段很多,难道就建很多的索引吗?
要知道,索引也是有开销的,首先,索引是以空间换取时间的,如果索引建的越多,占用的磁盘空间就越多,其次,每次对数据库进行写操作,索引也会进行相应的更新,也会影响数据库写操作的效率,总的来说,浪费了很多服务器的资源,所以索引需要合理的使用,以上的例子为例,我们可以建(co1,col2)的联合索引,这样查询的时候就可以通过(col1,col2)联合直接获取col1和col2字段的数据,直接返回。
覆盖索引是优化索引的重要方式之一
课外拓展-前缀索引
🌰举个例子,先建个表
CREATE TABLE `user` ( `ID` INT NOT NULL AUTO_INCREMENT, `Name` VARCHAR(50) NOT NULL, `City` VARCHAR(50) NOT NULL, `Age` INT NOT NULL, PRIMARY KEY (`ID`)
);
为了加快查询速度,我们给这个表加一个联合索引
ALTER TABLE user ADD INDEX 'name_city_name' (Name(10),City,Age)
仔细看就会发现在Name字段加了10长度限制,这就是前缀索引。Name字段长度是50,为什么用10呢?因为一般情况下名字长度不会超过10,这样不仅加快索引查询速度,还会减少索引文件的大小提高更新数据的效率。
五、索引使用建议
-
对较小的数据列使用索引
上面有提到过,索引文件会存储数据,所以选择数据量少的字段使用索引可以节省不必要的磁盘空间和内存的消耗 -
对 where、on、group by、order by 使用索引
-
对较长的字符串使用前缀索引
-
不要创建过多索引
-
多使用联合索引
在阿里云开发手册里,有一条要求是建表索引第一优先是使用联合索引。主要有一下原因:(1)减少开销
例如,建立一个联合索引(col1,col2,col3),实际相当于建(col1),(col2),(col3)三个索引。索引并不建的越多越好,每次对数据库进行写操作的时候,都需要对索引进行更新,所以建一个合理联合索引,可以节省数据库写和磁盘空间的开销。(2)覆盖索引
建了一个联合索引(col1,col2,col3),假如查询sql:select col1,col2,col3 from test where col1=1 and col2=2 ,那么数据库可以通过索引直接获取到数据,无需回表查询,减少了io操作。所以在实际开中,多使用联合索引以达到覆盖索引的效果,是很有效的优化手段之一。(3)增加查询效率
索引的利用效率更高,假如数据表有1000W条数据,有一条sql查询语句:select * from test where col1=1 and col2=2 and col3=3 ,假设可以通过每个索引查询条件筛选10%的数据第一种,如果只有一个普通索引col1,只能通过索引筛选出1000W * 10%=100W 条数据,然后在回表查找符合 col2 = 2 和 col3 =3 的数据,这样结果是回表扫描100W条数据。
第二种,如果是一个联合索引 (col1,col2,col3),能通过索引筛选出 1000W*10%*10%*10% = 1W 条数据,然后在回表查找表其他字段数据,效率的差别可想而知。
六、索引使用的要避免的坑
- 隐式转换问题(索引字段类型使用不准确,mysql会自动转换字段类型,从而导致索引失效)
- 对索引进行计算 (例如 age + 10 = 30 )
- 对索引使用函数运算 ( 例如 LEFT(
date
,4) ) - 正则表达式不使用索引(例如模糊查询%xx ,注意, xx% 是走索引的)
- or条件必须全部字段建立索引(少使用 or 条件)
七、索引的弊端
不要盲目的创建索引,只为查询操作频繁的列创建索引,创建索引会使查询操作变得更加快速,但是会降低增加、删除、更新操作的速度,因为执行这些操作的同时会对索引文件进行重新排序或更新。但是,在互联网应用中,查询的语句远远大于DML的语句,甚至可以占到80%~90%,所以也不要太在意,只是在大数据导入时,可以先删除索引,再批量插入数据,最后再添加索引。
相关文章:
Mysql的索引详解
零. 索引类型概述 1. 实际开发中使用的索引种类 主键索引唯一索引普通索引联合索引全文索引空间索引 2. 索引的格式类型 BTree类型Hash类型FullText类型(全文索引)RTree类型(空间索引) MySQL 的索引方法,主要包括 BTREE 和 HASH。 顾名思…...
.netcore windows app启动webserver
创建controller: using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks;namespace MyWorker.…...
泰迪大数据挖掘建模平台功能特色介绍
大数据挖掘建模平台面相高校、企业级别用户快速进行数据处理的建模工具。 大数据挖掘建模平台介绍 平台底层算法基于R语言、Python、Spark等引擎,使用JAVA语言开发,采用 B/S 结构,用户无需下载客户端,可直接通过浏览器进行…...
【问题】java序列化,什么时候使用
文章目录 是什么为什么如何做流操作 注事事项 是什么 把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列化主要有两种用途: 1)把对象的字节序列永久地保存到硬盘上,通常存放在一…...
【最新可用】VMware中ubuntu与主机window之间使用共享文件夹传输大文件
一、VMware设置共享文件夹 (1)虚拟机关机情况下,创建一个共享文件夹 (2)ubuntu中挂载共享文件夹 1、如果之前已经挂载 hgfs,先取消挂载 sudo umount /mnt/hgfs2、重新使用以下命令挂载 sudo /usr/bin/vmh…...
A. Two Semiknights Meet
题目描述 可知走法为中国象棋中的象的走法 解题思路 利用结构体来存储两个 K K K的位置 x , y x,y x,y,因为两个 K K K同时走,所以会出现两种情况 相向而行,两者距离减少 相反而行,两者距离不变 我们完全可以不考虑格子是好…...
〔011〕Stable Diffusion 之 解决绘制多人或面部很小的人物时面部崩坏问题 篇
✨ 目录 🎈 脸部崩坏🎈 下载脸部修复插件🎈 启用脸部修复插件🎈 插件生成效果🎈 插件功能详解🎈 脸部崩坏 相信很多人在画图时候,特别是画 有多个人物 图片或者 人物在图片中很小 的时候,都会很容易出现面部崩坏的问题这是由于神经网络无法完全捕捉人脸的微妙细节…...
在ubuntu+cpolar+rabbitMQ环境下,实现mq服务端远程访问
文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…...
Vue elementui 实现表格selection的默认勾选,翻页记录勾选状态
需求:当弹出一个列表页数据,对其进行筛选选择。 列表更新,填充已选数据 主要使用toggleRowSelection 代码如下: <el-table v-loading"loading" :data"drugList" selection-change"handleSelection…...
CloudCompare——统计滤波
目录 1.统计滤波2.软件实现3.完整操作4.算法源码5.相关代码 本文由CSDN点云侠原创,CloudCompare——统计滤波,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 1.统计滤波 算法原理见:PCL 统计滤波器…...
nodejs+vue古诗词在线测试管理系统
一开始,本文就对系统内谈到的基本知识,从整体上进行了描述,并在此基础上进行了系统分析。为了能够使本系统较好、较为完善的被设计实现出来,就必须先进行分析调查。基于之前相关的基础,在功能上,对新系统进…...
174-地下城游戏
题目 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻…...
Linux定时任务crontab
常用命令 crontab -e 进入定时脚本,编辑后保存即立即生效 crontab -l 查看用户定时脚本 tail -f /var/log/cron 查看执行日志 service crond status 查看定时器运行状态 service crond restart 重启定时器 定时任务不执行原因 定时任务设置的格式正确,手…...
golang字符串切片去重
函数的功能是从输入的字符串切片中去除重复的元素,并返回去重后的结果。具体的实现逻辑如下: 创建一个空的结果切片result,用于存储去重后的字符串。创建一个临时的maptempMap,用于存放不重复的字符串。map的键是字符串࿰…...
git如何检查和修改忽略文件和忽略规则
查询忽略规则 使用命令行:git status --ignored,进行查询, 例: $ git status --ignored On branch develop Your branch is up to date with origin/develop.Ignored files:(use "git add -f <file>..." to inc…...
Android AppCompatActivity标题栏操作
使用 AndroidStudio 新建的工程默认用 AppCompatActivity ,是带标题栏的。 记录下 修改标题栏名称 和 隐藏标题栏 的方法。 修改标题栏名称 Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R…...
解决conda activate报错
解决方法 source ~/anaconda3/bin/activate或 source ~/miniconda3/bin/activate然后就可以使用 conda activate xxx环境了 问题解析 请参考github:https://github.com/conda/conda/issues/7980...
FreeMarker--表达式和运算符的用法(全面/有示例)
原文网址:FreeMarker--表达式和运算符的用法(全面/有示例)_IT利刃出鞘的博客-CSDN博客 简介 本文介绍FreeMarker的表达式和运算符的用法。 表达式是FreeMarker的核心功能。表达式放置在插值语法(${...})之中时,表明需要输出表达…...
设计模式 -- 策略模式(传统面向对象与JavaScript 的对比实现)
设计模式 – 策略模式(传统面向对象与JavaScript 的对比实现) 文章目录 设计模式 -- 策略模式(传统面向对象与JavaScript 的对比实现)使用策略模式计算年终奖初级实现缺点 使用组合函数重构代码缺点 使用策略模式重构代码传统的面…...
非常详细的 Ceph 介绍、原理、架构
1. Ceph架构简介及使用场景介绍 1.1 Ceph简介 Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。 Ceph项目最早起源于Sage就读博士期间的工作(最早的成果于2004年发表),并随后贡献给开源社区。在经过…...
js 的正则表达式(二)
1.正则表达式分类: 正则表达式分为普通字符和元字符。 普通字符: 仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。 元字符: 是一些具有特殊含…...
星际争霸之小霸王之小蜜蜂(四)--事件监听-让小蜜蜂动起来
目录 前言 一、监听按键并作出判断 二、持续移动 三、左右移动 总结: 前言 今天开始正式操控我们的小蜜蜂了,之前学java的时候是有一个函数监听鼠标和键盘的操作,我们通过传过来不同的值进行判断,现在来看看python是否一样的实现…...
Visual Studio 2022 你必须知道的实用调试技巧
目录 1、什么是bug? 2.调试是什么?有多重要? 2.1我们是如何写代码的? 2.2又是如何排查出现的问题的呢? 编辑 2.3 调试是什么? 2.4调试的基本步骤 2.5Debug和Release的介绍 3.Windows环境调试介绍…...
Webgl 存储限定符attribute、gl.getAttribLocation、gl.vertexAttrib3f及其同族函数和矢量版本的介绍
目录 attribute变量规范 获取attribute变量的存储位置 gl.getAttribLocation()函数的规范: 向attribute变量赋值 gl.vertexAttrib3f()的规范。 gl.vertexAttrib3f()的同族函数 示例代码…...
postgresql跨库创建视图
需求: A库a表中的字段拆分1个到B库b表,所以b表中只保留唯一标识字段(可以理解为id)和另一个被拆分的字段 需要用到的拓展:CREATE EXTENSION dblink 使用dblink创建连接: SELECT dblink_connect(other_db, hostaddr【IP…...
FPGA时钟
几年前FPGA时钟只需要连接一个单端输入的晶振,非常容易。现在不同了,差分时钟输入,差分信号又分为LVDS和LVPECL,时钟芯片输出后还要经过直流或交流耦合才能接入FPGA,有点晕了,今天仔细研究一下。 FPGA输入…...
FifthOne:计算机视觉提示和技巧
一、说明 欢迎来到我们每周的FiftyOne提示和技巧博客,我们回顾了最近在Slack,GitHub,Stack Overflow和Reddit上弹出的问题和答案。FiftyOne是一个开源机器学习工具集,使数据科学团队能够通过帮助他们策划高质量数据集、评估模型、…...
Oracle19c-补丁升级报错合集(一)
前言: 本文主要介绍Oracle19c补丁升级遇到的问题,涉及安装补丁prepatch步骤,apply应用报错以及datapatch -verbose数据字典更新报错 问题一: 在执行补丁rootcrs.sh -prepatch操作时,发生执行检查命令cluutil -chkshare报错 CLSRSC-180: An …...
嵌入式:ARM Day6
作业:完成cortex-A7核UART总线实验 目的:1.输入a,显示b,将输入的字符的ASCII码下一位字符输出 2.原样输出输入的字符串 源码: uart4.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_rcc.h" #incl…...
ClickHouse安装步骤
文章目录 ClickHouse安装步骤背景安装启动用户相关修改密码登录验证新增用户config配置文件 基本操作服务管理 ClickHouse安装步骤 背景 经过研究ClickHouse是列式数据库,下面是在Centos7.9版本单机版的安装的演示 安装 首先安装yum-utils工具包 sudo yum inst…...
查看网站建设时间/广州营销型网站
自由软件永远是自由的! 近两天,很多媒体都转发了一篇文章,是讲 ASF(Apache Software Foundation) 和 GitHub 受美国法律限制的事情,部分业内人士也在担心,是否有可能中国的程序员们会受到限制的影响而不能使用 Apache …...
asp爆网站绝对路径/seo岗位工作内容
背景 大家都知道,我们在通过 Selenium 执行 Web 自动化测试时,每次都需要启动/关闭浏览器,如果是多线程执行还会同时打开多个,比较影响工作的正常进行。那有没有办法可以不用让浏览器的自动化执行干扰我们的工作呢? 7…...
网站建设公司那家好/关键词优化排名首页
李洪强iOS经典面试题156 - Runtime详解(面试必备) 一、runtime简介 RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数。…...
衡水安徽网站建设/如何分析百度指数
站在风口上,猪都能飞起来。人工智能风口,让Pyhon这门胶水语言转变成非常火的网红语言。编程功力深厚的程序员花一两个星期就能上手Python,而一些新手程序员花几个月就可以上手。学编程,用Python确实是一个相当不错的选择。不过&am…...
百度打击未备案网站/seo的外链平台有哪些
这是一篇有关莫比乌斯反演的总结 莫比乌斯反演是什么? 我也说不清 其实做完了这么多题后,我对莫反的理解就只是两个式子 然后在学莫反的过程中了解到了许许多多的套路,有用 最基础的,两个式子 我们假设有两个函数\(F(n)\)和\(f(n)…...
deramweaver做网站/系统优化是什么意思
dogdog是人类的朋友,古今中外,人们都很爱dog,英语中也有很多和dog相关的词汇。1.Every dog has its day.每条狗都有他的那天,意思就是人生总有出头之日,每个人都有春风得意的日子。2.Let sleeping dogs lie.让睡着的狗继续躺着吧!…...