MySQL数据库索引介绍
一、什么是索引
索引是mysql数据库中的一种数据结构,就是一种数据的组织方式,这种数据结构又称为key
表中的一行行数据按照索引规定的结构组织成了一种树型结构,该树叫B+树
二、为何要用索引
优化查询速度
注意:只能加速索引字段
三、如何正确的看待索引
错误的认知
项目上线之后,运行了一段是时间,发现项目运行极卡
- 想要加索引,最好提前加上,在开发之初,定位到常用的查询,为该字段提前创建索引,
- 在上线之后想加索引,光把问题定位到索引上就需要耗费很长时间,排查成本很高
索引越多越好
- 索引使用与加速查询的,降低写效率
- 如果某一张表的ibd文件中创建了很多棵索引树,意味着很小一个updata语句就会导致很多棵索引数都需要发生变化,从而把硬盘io打上去
四、储备知识
索引的根本原理就是把硬盘的io次数降下来
- 为一张表中的一行行记录创建索引就是为书的一页页内容创建目录
- 有了目录以后,我们以后的查询都应该通过目录去查询
一次磁盘io带来的影响
7200转/分钟
120转/s
慢在找的过程,读的过程是快的,(统称延迟时间)
一次io的延迟时间=平均寻道时间(大概需要5ms)+平均延迟时间(4ms)---》9ms
9ms对于一个人来说是很慢的,但是对于计算机来说是很长的,比如一台500 -MIPS 的机器每秒可以执行5亿条指令,应为指令是靠电的性质,换句话说就是执行一次io的时间可以执行450万条指令,数据动则十万百万乃至千万条数据,每次9ms的时间显然是一个灾难。
磁盘的预读
- innodb存储引擎一页16k,即一次io读16k,
- 当一次io时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓存区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。
五、创建索引的两个步骤
crate index xxx on user(id);
- 提取索引字段的值当做key,value就是对应本行记录
- 以key为基础比较大小,生成树型结构
创建索引最好是以占空间小,重复度低的字段创建索引
六、B+树
innodb存储引擎默认的索引结构为B+ 树,而B+树是由二叉树、平衡二叉树、B树演变而来的。
二叉树——》平衡二叉树——》B 树 ——》B + 树
基本概念:
leaf node:叶子节点
non-leaf node:根节点、树枝节点
二叉树:
二叉树有一个特点,它的左节点的 key 值小于当前节点的 key 值,而它的右节点 key 值大于当前节点 key 值。
创建二叉树索引

取每一条记录的id值作为key值,value为本行完整记录,构建了树型结构后,查找的速度根树的高度有关系。
平衡二叉树:
平衡二叉树又称为AVL树,指的就是左子树的高度与右子树的高度相差不超过1,如下图所示;

平衡二叉树相比于二叉树来说,查找效率更稳定,总体的查找速度也更快,但是并不是基于平衡二叉树构建索引就可以的。因为每个磁盘块只放一个节点,每个节点只放一组键值对,当数据过大的时候,二叉树的节点就会非常多,树的高度也会变高,查找的效率也会变低!
B 树:
就是构建一个单节点可以存储多个键值对的平衡树,就是B树。

B树相对于平衡二叉树,每个节点存储了更多的键值和数据,每个节点有更多的子节点,子节点的个数称为阶,上图就是一个3阶B树,高度也会很低,这样B树的查找磁盘次数也会很少,这样数据的查找效率就会比平衡二叉树高。
B+ 树:
B+ 树是对B树的进一步优化。

B+ 树和B 树有什么不同
B+ 树非叶子节点non-leaf node 上是不存储数据的,仅存储键,而B 树的非叶子节点中不仅存储键,也会存储数据。B + 树之所以这么做的意义在于;树一个节点就是一个页,而数据库中页的大小是固定的,innodb 存储引擎默认一页为16kb,所以在页大小固定的前提下,能往一个页中放入更多的节点,相应的树的阶数就会更大,那么树的高度必然更矮更胖,如此一来我们查找数据进行磁盘io次数又会再次减少,数据查询的效率也会更快。
B+ 树的阶数是等于键的数量的,列如我们的B+ 树中每个节点可以存储3个键,3层B+ 树可以存储
3*3*3=9个数据。所以如果我们的B+ 树一个节点可以存储1000个键值,那么3层B+ 树可以存储1000*1000*1000=10亿个数据。而一般节点是常驻内存的,所以一般我们查找出10亿数据,只需要2次磁盘IO。因为B+ 树索引的所有数据均存储在叶子节点leaf node ,而且数据是按照顺序排列的。那么B+ 树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而B 树因为数据分散在各个节点,要实现这一点是很不容易的。
而且B+ 树中各个页之间也是通过双向链表连接的,叶子节点找那个的数据是通过单向链表连接的。其实在B 树中我们也可以多各个节点加上链表。其实这些不是它们之间的区别,是因为在mysql的innodb存储引擎中,索引及时这样存储的。也就是说B+ 树索引就是innodb中 B+ 树索引真正的实现方式,准确的说应该是聚集索引。
在innodb中,我们通过数据页之间通过双向链表连接以及叶子节点中数据之间通过单向链表连接的方式可以找到表中所有的数据。
七、B+ 树分类
聚集索引、聚簇索引、主键索引:
以主键字段值为key构建的B+ 树,改B+ 树的叶子节点放的是主键值与本行完整的记录。
即:表中的数据都聚聚在叶子节点中,所以称之为聚集索引。
非聚集索引、非聚簇索引、辅助索引、二级索引:
以非主键字段值为key构成的B+ 树,改B+ 树的叶子节点放的是key与其主键对应的字段值。
补充:一张innodb 存储引擎中有且只能有一张聚集索引,但是可以有多个非聚集索引(辅助索引)
聚集索引负责聚集整张表的所有的数据,而辅助索引是专门提速来用
八、覆盖了索引、回表操作
覆盖了索引:在命中了索引的基础上,只在本索引树的叶子节点就找到了我们想要的数据。
回表操作:在命中了辅助索引的基础上,在辅助索引的叶子节点并没有找想要的数据,需要拿到对应的主键字段值去聚集索引去找。
举例:假设我有一张表,我们这张表是以ID字段为基础创建的主键索引,我是以name字段创建的辅助索引
主键索引——》id字段
辅助索引——》name字段
select name, age, gender from user where name='yang';
这个命中了辅助索引,那么就顺着索引树从根节点一路找下去,找到叶子节点后,叶子节点放的是 ‘yang’ 这个人名以及它的主键字段值
但是我要的是name age gender ,我要的不是id值和主键值,如果我要的是主键值和id值那么我就不需要去其他地方找了——》这就叫覆盖了索引。
因为在自己本索引树的,本索引树的就能找到自己想要的数据,就不需要去别的地方找
但是这并不是我想要的,那么我要拿着我 ‘yang’的主键字段值假如是3,就回过头继续去主键索引树根节点继续找到我想要的叶子节点的数据,那里面所有数据都有——》这就叫回表操作
提问:
1、命中了辅助索引的前提下能不能覆盖了索引?
可能是!向这种情况下就是select name, id from user where name='yang'; '
这就不是select name, age, gender from user where name='yang';
2、如果命中了主键索引是否覆盖了索引?
一定是!·select name, age, gender from user where id=3;
所以一个SQL语句查询的字段尽量不要想写什么就写什么甚至是 * ,要尽量覆盖了索引。
九、索引管理
MySQL常用的索引分类
聚集索引:即主键索引,primary key
用途:
1.加速查找
2.约束(不为空,不能重复)
辅助索引:
唯一索引:unique
用途:
1.加速查找
2.约束(不能重复)
普通索引:index
用途:
1.加速查找
创建聚集索引
alter table 表名 add prmary key 表名(字段名);
alter table 表名 drop primary key;——>删除
创建唯一索引
alter table 表名 add unique key 表名(字段名); 没有写索引名 show create table 表名; 查看
alter table 表名 drop index 索引名;——>删除
创建普通索引
创建表时
create table 表名(
id int primary key auto_increment,
class_name varchar(10) unique,
name varchar(16),
age int
);
创建表后
create index 索引名 on 表名(字段名);
drop index 索引名 on 表名;——>删除
十、联合索引最左前缀匹配原则
create index zz on t1(id, name,age)
例如:有这样的数据
id name age gender email
1 yang1 18 male yy@qq.com
2 yang2 28 female yy@qq.com
3 yang3 38 male yy@qq.com
4 yang4 48 female yy@qq.com
我现在对它们建联合索引,那么我每条记录提取的key就是 id,name,value对应的是该条记录,列如:
1,yang1,18 ————>对应 1 yang1 18 male yy@qq.com
2,yang2, 28 ————>对应 2 yang2 28 female yy@qq.com
那么,当初只有一个字段的时候比大小的时候很好比,那两个字段值怎么比大小?
1,yang1,18
2,yang2,28
注意这个和字符串比大小一样,从左到右一个一个比,第一个如果分胜负了,就没有必要在比联合的了第二个字段了
在查询条件中出现了id name,age字段那么就肯定能命中这个联合索引
但是必须带着id、例如:id name、id age、id age name
最核心的原理就是每次从最左边第一个位置开始比大小,通过最左边就能够缩小范围,这就是最左前缀匹配原则。
什么时候建立联合索引?
联合索引就只有一棵树,当不用联合索引聚集索引和辅助索引就需要建三棵树,这样就浪费了空间。
如果要平凡的用这几个字段来一起查询,就可以考虑建立联合索引,就一棵树。
但是注意在查询条件中一定要带有最左边的字段
总结:如果查询条件中涉及到多个字段值,这多个字段值有一个同性,大家都会带着某一个字段,那这时候就可以键联合索引。
MySQL数据库索引介绍的更多相关文章
- MySQL数据库引擎介绍、区别、创建和性能测试的深入分析
本篇文章是对MySQL数据库引擎介绍.区别.创建和性能测试进行了详细的分析介绍,需要的朋友参考下 数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...
- MySQL数据库索引的4大类型以及相关的索引创建
以下的文章主要介绍的是MySQL数据库索引类型,其中包括普通索引,唯一索引,主键索引与主键索引,以及对这些索引的实际应用或是创建有一个详细介绍,以下就是文章的主要内容描述. (1)普通索引 这是最基本 ...
- [转]MySQL数据库引擎介绍、区别、创建和性能测试的深入分析
本篇文章是对MySQL数据库引擎介绍.区别.创建和性能测试进行了详细的分析介绍,需要的朋友参考下 数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...
- (转)MySql数据库索引原理(总结性)
本文引用文章如链接: http://www.codinglabs.org/html/theory-of-mysql-index.html#more-100 参考书籍:Mysql技术内幕 本文主要是阐述 ...
- 知识点:Mysql 数据库索引优化实战(4)
知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 一:插入订单 业务逻辑:插 ...
- 为什么MySQL数据库索引选择使用B+树?
在进一步分析为什么MySQL数据库索引选择使用B+树之前,我相信很多小伙伴对数据结构中的树还是有些许模糊的,因此我们由浅入深一步步探讨树的演进过程,在一步步引出B树以及为什么MySQL数据库索引选择使 ...
- MySQL数据库索引之B+树
一.B+树是什么 B+ 树是一种树型数据结构,通常用于数据库和操作系统的文件系统中.B+ 树的特点是能够保持数据稳定有序,其插入与修改操作拥有较稳定的对数时间复杂度.B+ 树元素自底向上插入,这与二叉 ...
- 第二百八十八节,MySQL数据库-索引、limit分页、执行计划、慢日志查询
MySQL数据库-索引.limit分页.执行计划.慢日志查询 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获 ...
- MYSQL数据库索引类型及使用
MYSQL数据库索引类型包括普通索引,唯一索引,主键索引与组合索引,这里对这些索引的做一些简单描述: (1)普通索引 这是最基本的MySQL数据库索引,它没有任何限制.它有以下几种创建方式: 创建索引 ...
随机推荐
- 【LeetCode】761. Special Binary String 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/special- ...
- 【LeetCode】5. Longest Palindromic Substring 最长回文子串
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:最长回文子串,题解,leetcode, 力扣,python ...
- 1018 - Brush (IV)
1018 - Brush (IV) PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Muba ...
- rabbitmq集群和镜像队列
Rabbitmq集群和镜像队列 1引言 1.1编写目的 2 原理和使用 2.1镜像队列原理 2.1.1 原理 默认的一个rabbitmq中的queue是在一个node上的,至于在那个node上取决于c ...
- [技术干货-算子使用] Mindspore 控制流中存在原地更新操作类副作用算子时循环值不更新问题记录
关于mindspore 原地更新类算子的一点思考记录如下: 现象记录: 原始测试代码 错误结果复现: 分析: 如果在场景中加入42行的copy()操作此时cpu的结果就会正确,但是gpu的结果则不受c ...
- [Guide]Google Python Style Guide
扉页 项目主页 Google Style Guide Google 开源项目风格指南 - 中文版 背景 Python 是Google主要的脚本语言.这本风格指南主要包含的是针对python的编程准则. ...
- Java EE数据持久化框架 • 【第6章 MyBatis插件开发】
全部章节 >>>> 本章目录 6.1 MyBatis拦截器接口 6.1.1 MyBais拦截器接口介绍 6.1.2 MyBais拦截器签名介绍 6.1.3 实践练习 6.2 ...
- JSP中使用<c:forEach>标签循环遍历元素
1.forEach标签元素 <c:forEach items="接收集合对象" var="迭代参数名称" varStatus="迭代状态,可访问 ...
- Java程序设计基础笔记 • 【目录】
持续更新中- 我的大学笔记>>> 章节 内容 实践练习 Java程序设计基础作业目录(作业笔记) 第1章 Java程序设计基础笔记 • [第1章 初识Java] 第2章 Java程序 ...
- Error: Cannot find module '@dcloudio/uni-cli-i18n' 解决方案
这个错误是因为node_modules缺少了 '@dcloudio/uni-cli-i18n' 以下是错误信息 解决方案: yarn add -D @dcloudio/uni-cli-i18n ...