【一文读懂】Mysql索引原理之环环相扣
MySQL为什么要使用索引?
MySQL读写比例一般是10:1,大部分性能瓶颈在查询,所有优化性能的关键点都在查询,而索引可以有效的提升MySQL的查询性能。
为什么索引能提升查询性能?
索引通过特殊的数据结构和查询方式,能有效减少查询范围,减少IO的参数,从而提升查询效率
究竟什么是索引呢?
数据库索引本质上是一种数据结构(存储结构+算法),目的是为了加快搜索性能
那数据库索引的数据结构是什么样的?
以InnoDb引擎为例,主要支持三种数据结构,B+树、哈希索引、R树:
哈希索引:
实现原理:由索引列来决定存储位置。
优点:检索效率非常高,索引的检索可以一次到位,复杂度为O(1)
缺点:
1.索引无序,无法进行范围查询,只能用作IN,==等查询;无法排序
2.每次都要全表扫描
3.不符合最左缀原则,不能用部分索引建来搜索
4.当哈希值大量重复且数据量非常大时,由于哈希碰撞,查询效率会很低
B+树索引:
实现原理:参考【一文读懂】二叉树,平衡二叉树(AVL),红黑树,B+树的原理
优点:
1.与B-Tree比较,内节点不存储data只存储Key,叶子结点不存储指针,在大数据量情况下,能有效的减少IO次数
2.B+树的查询必须最终找到叶子节点,而B-树只需要找到匹配的元素即可,无论匹配元素是中间节点还是叶子节点。
因此B-树的查找性能不稳定(最好情况是只查根节点,最坏查到叶子节点),而B+树每次查找都是稳定点
3.B-树只能依靠繁琐的中序遍历,而B+树只需要在链表上遍历即可。范围查询更方便
4.B更充分利用磁盘预读
缺点:
精确查询效率不如哈希索引
R树索引:空间索引适用。
数据库索引怎么实现的?
在MySQL中,不同存储引擎对索引的实现方式是不同的,引擎主要有MyISAM(图1)和InnoDB(图2)两种
聚集索引:一种索引,该索引中键值的逻辑顺序决定了表中相应行的物理顺序。
非聚集索引:一种索引,该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。
相同点:
- 索引的数据结构都是B+Tree
不同点:
- MyISAM索引与数据文件分离,InnoDB数据文件本身就是索引文件
- MyISAM主索引叶结点的data域存放的是数据记录的地址(非聚集索引),InnoDB叶节点存放的则是完整的数据记录(聚集索引)。
- MyISAM辅助索引叶结点的data域存放的是数据记录的地址(和主索引一样), InnoDB的辅助索引data域存储相应记录主键的值。
- MyISAM对主键无要求,InnoDB要求主键最好不要过长(因为每一个辅助索引都引用主键)
图1 MyIASM主索引(左)和辅助索引(右)
图2 InnoDB主索引(左)和辅助索引(右)
如何确定索引是否执行?
在select语句之前加入explain关键字,通过查看type字段可以确定是否使用索引(为All表示未使用索引),possible_keys列出所有可能使用的索引,key是优化器选择后真正使用的索引
type 常用的类型有: ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index: Full Index Scan,index与ALL区别为index类型只遍历索引树
range:只检索给定范围的行,使用一个索引来选择行
ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system
NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
MySQL如何选择索引?
采用查询优化器
MsSQL不使用索引的可能情况?
- MySQL估计使用索引比全表扫描更慢,则不使用索引
- 复合索引,如果索引列不是复合索引的第一部分,则不使用索引(即不符合最左前缀)
- 如果like是以‘%'开始的,则该列上的索引不会被使用。例如
select * from table_name where key1 like '%a'
;该查询即使key1上存在索引,也不会被使用。 - 如果列为字符串,则where条件中必须将字符常量值加引号,否则即使该列上存在索引,也不会被使用。
MySQL索引优化规则?
索引创建:
- 如果建立了(a,b)联合索引,就不必再单独建立 a 索引。同理,如果建立了(a,b,c)联合索引,就不必再单独建立 a、(a,b) 索引。
- 存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如 where a>? and b=?,那么即使 a 的区分度更高,也必须把 b 放在索引的最前列。最左侧查询需求,并不是指 SQL 语句的 where 顺序要和联合索引一致(优化器会自动调整),但是推荐顺序保持一致。select * from table where a<100 and b=10
利用覆盖索引来进行查询操作,避免回表。比如下面语句,可以建立索引(a,b,c)覆盖索引(所有数据都在索引里面),避免回表。select id, a from table where b=? and c=?
如果有 order by,可以建立联合索引,将order by的字段放在联合索引最后(防止file_sort的情况,影响性能)
业务上具有唯一特性的字段,必须建成唯一索引。
单表索引建议控制在5个以内,单索引字段数不允许超过5个。
尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
索引使用:
- 建立索引的列,不允许为 null。应尽量避免在 where 子句中对字段进行 null 值判断;尽量避免在 where 子句中使用!=或<>操作符。
- 范围列可以用到索引(联合索引必须是最左前缀)。但是范围列后面的列无法用到索引,索引最多用于一个范围列。比如联合索引(a,b),在下面语句中,只能a用到索引,b用不到
in 和 not in 也要慎用,多值查询一般是走索引的。但能用 between 就不要用 in,也可以考虑用exists代替。
不要在SQL操作中计算
SQL 性能优化 explain 中的 type:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。
索引口诀:
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用。
送上一波练习题?
https://www.cnblogs.com/developer_chan/p/9223671.html
【一文读懂】Mysql索引原理之环环相扣相关推荐
- mysql 默认事务隔离级别_一文读懂MySQL的事务隔离级别及MVCC机制
回顾前文: <一文学会MySQL的explain工具> <一文读懂MySQL的索引结构及查询优化> (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论 ...
- 一文读懂 MySQL Explain 执行计划
一.前言 上周老周的一个好朋友让我出一篇教你读懂 SQL 执行计划,和我另一位读者反馈的面试题如何排查慢 SQL 的强相关,索性先出一篇一文读懂 MySQL Explain 执行计划.Explain ...
- 一文读懂贝叶斯原理(Bayes‘ theorem)
一文读懂贝叶斯原理(Bayes' theorem) 前言:贝叶斯定理是18世纪英国数学家托马斯·贝叶斯(Thomas Bayes)提出得重要概率论理论.以下摘一段 wikipedia 上的简介: 一. ...
- 一文读懂CDN加速原理
一文读懂CDN加速原理 什么是 CDN 工作原理 传统访问过程 CDN 访问过程 组成要素 智能调度 DNS 缓存功能服务 负载均衡设备 内容 Cache 服务器 共享存储 名词解释 CNAME记录( ...
- 一文搞懂 MySQL 索引
一文搞懂 MySQL 索引 1.MySQL 索引 简介 1.1.MySQL 索引 是什么? 索引是一个单独的.存储在 磁盘 上的 数据库结构 ,包含着对数据表里 所有记录的 引用指针. 1.2. M ...
- ❤『知识集锦』一文搞懂mysql索引!!(建议收藏)
作者:不吃西红柿 简介:CSDN博客专家.蓝桥签约作者.大数据领域优质创作者. 以我的资历和文凭,将来这个城市的大街,都归我扫. [系列课程介绍] 『面试知识集锦』系列课程包括以下20个系列,超过 ...
- 十二、一篇文章帮助你快速读懂MySQL索引(B树、B+树详解)
2. 索引 2.1 索引概述 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序).在数据之外,数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某 ...
- [数据库] 一文读懂Mysql数据库索引实现原理
咱们用了这么久Mysql数据库做项目,你知道数据是怎么存在数据库里吗?他们是如何存储的吗? 今天咱们就来扒一扒Mysql数据库索引的底层实现,Mysql数据库的索引是由都是由B+树实现的,那为什么不是 ...
- 一文读懂MySQL事务锁、事务级别
锁 性能分:乐观(比如使用version字段比对,无需等待).悲观(需要等待其他事务) 乐观锁,如它的名字那样,总是认为别人不会去修改,只有在提交更新的时候去检查数据的状态.通常是给数据增加一个字段来 ...
最新文章
- 从消费端到企业端,从设备到数据:物联网市场的爆发式增长
- JavaScript —— 如何判断一个非数字输入
- cgi,fastcgi,php-cgi,php-fpm之间的关系
- 如何去设计硬件与程序之间的通信协议
- kibana 更新 索引模式_Kibana对索引动态加字段显示
- 拨盘Demo大赛,获奖公布-20170710
- mysql数据库加权随机_SQL:随机选择一行,但考虑到权重
- php压缩zip文件类
- VMware vsphere中虚拟机的基本操作方法
- 米小爱团队负责人王刚:语音交互背后,有多少人工就有多少智能
- input[type=radio]自定义样式
- 查看svn的版本(转载)
- 如何使用USB摄像头搭配Visionpro进行视觉识别
- Javaweb邮箱验证注册的实现
- oracle 卸载(手动,无universal installer)
- gb和gib的区别_高端存储手册里面的KiB,MiB,GiB是啥意思?
- 基于PyQt5与opencv制作的证件照尺寸变换应用程序
- 图片降噪Topaz DeNoise AI 安装小技巧
- Win7下chm文件打不开的解决办法
- MYS-6ULX-IOT 开发板测评——支持 RTL8188 WiFi 模块