终于有人把MYSQL索引讲清楚了
一什么是索引
索引在MYSQL中也可以称为键,其是存储引擎用于快速查找记录的一种数据结构;这样听起来有点生涩,你可能难以理解;如果给你一本书,你如何能够精确的查找到书中某个章节的具体位置呢?我们肯定是先看目录,再找内容。你可以理解索引就像书的目录一样;当数据库的数据量大的时候,索引的性能对数据库非常重要,索引分为很多种,所以要学习好索引的相关知识,甚至比查询优化更重要。
二B-Tree与 B+Tree
2.1B-tree树
学习B-树之前读者肯定要有二叉树的基础知识,(没学过的看这篇
https://blog.csdn.net/youku1327/article/details/105159762)
MYSQL中的数据结构实际上是B+tree,而非Btree;所以我们先要了解一下什么是Btree,再了解下一下什么是B+tree; 要得出的结论是为什么MYSQL要使用B+tree, 而非 Btree;
M阶B-tree的特征如下
- 根节点至少有两个子女.
- 每个节点包含k-1个元素和k个孩子,其中m/2 <= k <= m.
- 每一个叶子节点都包含k-1个元素,其中m/2 <= k <= m.
- 所有的叶子节点位于同一层.
- 每个节点中的元素从小到大排列,那么k-1个元素正好是k个孩子包含的值域的划分
如果没学过数据结构的读者看到这边肯定一头雾水,知识追寻者还是做个简单的说明;如下图3阶B-树所示;
- 根节点9包含两个子节点,(3,7)一个节点,12 一个节点;
- (m/2=1) <= k <= (m=3); 所以节点包含1至3个都正确,故 (3,7)和 12 满足要求;
- 再看 2 小于 3 位于 3左侧,(4,5)大于3小于7位于(3,7)中间,8大于7位于7右侧;

树的高度决定了磁盘的IO能力,一棵3阶的B-磁盘IO能力为3,与二叉树IO能力相同;数据库加载索引的时候是加载磁盘页(默认4K大小),而非整个索引,每个磁盘页都对应索引的记录,故B-树并不能带来高效磁盘IO;
从树的形态上B-树比二叉树更加的胖,原因也很简单,B-树的节点可能包含多个元素;
注:B树就是B-树,面试的时候别说B减树;
2.2B+tree树
B+树是B-树的基础上进行升级,B+树的特征如下
- 每个中间节点不保存数据,用来保存索引,叶子节点存放数据;
- 中间节点都存在于叶子节点,为最大值或者最小值,所以会出现重复的现象;
- 叶子节点之间根据自身的顺序进行了链接;

对B+树也做个简单说明:
- 中间节点 (2,5,8)和(11,16)都没有存放数据,并且都是叶子节点存放数据;
- 8,16同时存在于中间节点,叶子节点;同理(2,5,8)这个节点的元素都存在于叶子节点;
2.3B+比B-优势
B+比B-的优势在哪里,面试经常问道;
- B+树的中间节点不存放数据,磁盘页可以存放更多的节点元素;
- B+Tree非叶子节点不存储数据,所有的数据都要查询至叶子节点,而叶子节点的高度都是相同的,因此所有数据的查询速度都一样;而B-树根据精确的匹配查找,查找数据不稳定;
三 索引
3.1 非聚集索引和聚集索引
MySQL中最常见的两种存储引擎分别是MyISAM和InnoDB,分别实现了非聚集索引(普通索引)和聚集索引;
聚集索引:聚集索引的顺序就决定了数据行的物理存储顺序;所以我们创建的主键索引其实就是聚集索引,如果未定义主键,MYSQL会默认选择非空的唯一索引当作主键,否则会默认生成一个主键
非聚集索引:索引顺序与数据行物理排列顺序无关;
看下普通索引如何创建,其作用就是加快查询速度;
语法格式如下
alter table 表名 add index 索引名称(索引字段)
如果创建表的时候语法格式如下
CREATE INDEX 索引名称 ON 表名 (索引字段)
知识追寻者手头有一张用户表,模拟10万数据;
未创建索引查询速度
select * from sys_user where first_name = 'ijklmnopqrs'
> OK
> 时间: 0.059s
创建索引
alter table sys_user add index select_username(first_name)
创建索引后查询速度
select * from sys_user where first_name = 'ijklmnopqrs'
> OK
> 时间: 0.049s
删除索引
DROP INDEX [索引名称] ON 表名;
查看索引
SHOW INDEX FROM 表名;
3.2索引的分类
Mysql中索引的种类也不是很多,不同类型的索引有不同的作用,索引的作用相互之间也存在交叉关系,Mysql中索引主要分为以下几类:
- 主键索引(
PRIMARY KEY):主键索引一般都是在创建表的时候进行指定,一个表只有一个主键索引,特点是唯一、非空。MYSQL常用就是 自增主键; - 唯一索引(
UNIQUE):唯一索引具有的特点就是唯一性,即指定列不能出现重复数据; - 前缀索引(
prefix INDEX):前缀索引建立的基础就指定列数据有很多的共同前缀; - 联合索引:联合索引又称符合索引,是在表中两个或者两个列以上的基础上创建索引;
- 覆盖索引:当一个索引包含(或者说是覆盖)需要查询的所有字段的值时,我们称之为覆盖索引;
3.3 主键索引和唯一索引
主键索引我们通常不默认,经常使用,一张表中仅允许有一个主键,可以由一个或者多字段组成;主键索引满足如下特征:
- 主键必须唯一;
- 主键不能包含NULL值;
- 主键必须自增;
创建主键语法格式
alter table 表名 add primary key (字段名称)
创建唯一索引语法格式:
alter table 表名 add unique (字段名称)
如果是创建表时添加约束语法格式
CREATE UNIQUE INDEX 索引名称 ON 表名(字段(字段长度));
3.4 前缀索引
前缀索引: 当对字符串进行索引时,如果数据库中该字段有许多的前缀重复就可以使用前缀索引,,这样可以大大的节约索引空间,从而提高索引效率;但其缺点也很明显,不能在 order by 和 group by 中使用;
前缀索引经常使用在地名,比如 xx省xx市xx县这种情形,有一个统一的前缀 xx省xx市;
创建语法
alter table 表名 add key (字段名称(前缀长度))
示例
alter table sys_user add key (first_name(8))
查询的时候使用指定前缀的长度性能更加
select * from sys_user where first_name = 'ijklmnop'
3.5 覆盖索引
回表查询:
MYSQL 如果只通过索引就可以返回查询所需要的数据,就是不是回表查询,否则查到索引数据后还需要回到表中查询数据就是回表查询;
我们来看个简单的示例
先去除前缀索引
drop index first_name on sys_user
然后加上普通索引
alter table sys_user add index select_username(first_name)
实行MYSQL执行计划
(没学过MYSQL执行计划看这篇 https://blog.csdn.net/youku1327/article/details/107336500)
explain select id from sys_user where first_name = 'ijklmnop'
输出结果表示 使用using index , 由于 id 和 first_name 都是索引;所以不需要回表查询就是覆盖索引;

如果我们使用如下语句则需要回表查询,原因是查询到字段id, first_name后还需要回表查询其它字段,这就是为什么 select * 如此慢的原因;
explain select * from sys_user where first_name = 'ijklmnop'
输出结果如下

3.6 联合索引
联合索引是在表中用2个或者2个以上的字段创建索引,其创建索引方式与普通索引相同;其能减小检索范围;
语法格式
alter table 表名 add index 索引名称(字段1,字段2...)
最左前缀匹配原则
使用联合索引有一个非常重要的因素就是所有的索引列只可以进行最左前缀匹配原则;
比如
联合索引 first_name和 last_name
alter table sys_user add index select_username(first_name,last_name)
根据最左匹配原则情形如下会命中索引
- first_name,last_name
- first_name
转换为查询语句命中索引示例如下
select * from sys_user where first_name = 'ijklmnop';
select * from sys_user where first_name ='ijklmnop' and last_name ='ijklmnop';
select * from sys_user where first_name ='ijklmnop' and last_name in (ijklmnop');
select * from sys_user order by first_name,last_name
select * from sys_userwhere first_name ='ijklmnop'order by last_name
如下情形不会命中索引
select * from sys_user where last_name = 'ijklmnop';
select * from sys_userwhere last_name ='ijklmnop'order by first_name
索引下推
Mysql5.6版本发布了索引下推的原则,主要用于like关键字的查询优化 ;
比如联合索引(last_name,age)
select * from sys_user where last_name = 'ijklmnop' and age>'20';
命中可能性如下
- 命中last_name联合索引,查询所有满足last_name以"ijklmnop"开头的数据, 然后回表查询所有满足的行。
- 命中last_name联合索引,查询所有满足last_name以"ijklmnop"开头的数据,然后再筛出age>20的索引,再回表查询全行数据。
第二种方式的磁盘IO会更少,查询效率会更高,这就是下推索引;
除此之外还有全文索引和hash索引,简单了解一下即可;
四 索引总结
4.1索引的优点
- 提高查询效率
- 提高聚合函数查询效率
- 提高排序查询效率
- 使用覆盖索引避免回表
4.2创建索引的策略
- 不要在NULL值列上使用索引,尽量使用NOT NULL约束列上使用索引
- 很少查询的字段不要使用索引
- 大数据类型字段不创建索引
4.3 使用索引时的注意事项
- 不要在条件NOT IN、<>、!= 等范围查询中使用索引
- 模糊查询时不要使用 %开头( 如 '%xxx' , '%xxx%')
- 查询索引的字段不要函数计算
- 联合索引查询时遵循最左原则
- 全部扫描超过30%不会走优化器;
听说关注公众号 知识追寻者 的男孩子都找到了漂亮的女朋友,女孩子都找到了白马王子;当然索引并非查询优化的最佳原则,但在大多数情况下就已经足够使用;在大数据情况下通常要考虑分库分表;

终于有人把MYSQL索引讲清楚了的更多相关文章
- 【转】MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- [转]MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- [纯干货] MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- MySQL 索引背后的数据结构及算法原理
本文转载自http://blog.jobbole.com/24006/ 摘要本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引 ...
- 浅谈MySQL索引背后的数据结构及算法
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- 浅谈MySQL索引背后的数据结构及算法(转载)
转自:http://blogread.cn/it/article/4088?f=wb1 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储 ...
- MySQL索引背后的数据结构及算法原理 --转
写在前面的话 在编程领域有一句人尽皆知的法则“程序 = 数据结构 + 算法”,我个人是不太赞同这句话(因为我觉得程序不仅仅是数据结构加算法),但是在日常的学习和工作中我确认深深感受到数据结构和算法的重 ...
- 浅谈MySQL索引背后的数据结构及算法【转】
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
随机推荐
- ElasticSearch 7.X版本19个常用的查询语句
整理一篇常用的CRUD查询语句,之前这篇文件是在17年左右发表的,从英文翻译过来,现在采用7.x 版本进行实验,弃用的功能或者参数,我这边会进行更新,一起来学习吧. 为了演示不同类型的 Elastic ...
- Mybatis中List传值
Mybatis遇到List传值时常用方法. 1. List<E>,E为基本数据类型和String Mapper类文件: List<User> selectByIds(List& ...
- JAVA 读取excel文件成List<Entity>
package com.fsinfo.common.utils; import com.fsinfo.modules.enterprise.entity.EnterpriseRecordEntity; ...
- 关于Redis的工作模式
1.哨兵模式 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master. 缺点 ...
- 1 Spark概述
第1章 Spark概述 1.1 什么是Spark Spark是一种快速.通用.可扩展的大数据分析引擎,2009年诞生于加州大学伯克利分校AMPLab,2010年开源,2013年6月成为Apache孵 ...
- 随机陷阱和P值
如果让大家写一个50次的抛硬币实验的可能结果(头像H或字T),多半人在连续三个一样的后,会换一下.因为大家都知道,连续一样的越多,概率越小,越不可能发生.大部分人不会去想,其实HHHTT和HHHHH发 ...
- Netbox 开源 IPAM 管理工具搭建详细流程
原文链接:Netbox 开源 IPAM 管理工具搭建详细流程 参考资料:https://netbox.readthedocs.io/en/stable/ PostgreSQL数据库安装 1.yum 下 ...
- 七夕节表白3d相册制作(html5+css3)
七夕节表白3d相册制作 涉及知识点 定位 阴影 3d转换 动画 主要思路: 通过定位将所有照片叠在一起,在设置默认的样式以及照片的布局,最后通过设置盒子以及照片的旋转动画来达到效果. 代码如下: &l ...
- JavaGUI之Swing简单入门示例
简介 AWT(译:抽象窗口工具包),是Java的平台独立的窗口系统,图形和用户界面器件工具包. Swing 是为了解决 AWT 存在的问题而以 AWT 为基础新开发的包(在使用Swing时也常会用到j ...
- 如何为指定python解释器安装pip
有时候我们通常会有很多python解释器,例如python2.python3.python(Anaconda). 参考链接:https://www.cnblogs.com/michaelcjl/p/1 ...