MySQL-带你上官网看索引
在我之前的一篇文章中,有引用一个讨论用Hash还是Tree的问题,DB中关于查找类数据结构,除了树,还有Hash(HashMap,HashSet)。
存储数据结构之争
B+树主要是照顾磁盘IO这种特殊的性质应运而生的;然而在内存够多够大时,Hash某些时候比Tree结构有用得多。
但是Hash做索引的缺点也非常明显:
1,Hash冲突造成的散列不均匀,线性查找浪费时间;
2,不支持范围查询,避免不了全表扫描;
3,内存空间要求高。
MySQL中,InnoDB和MyISAM默认的索引是B+ Tree索引;Memory则同时支持Hash和Tree索引(可在创建时直接指定使用何种索引,具体移步)。
同时,Memory这种存储引擎“断电即毁”的特性也不再推荐使用。
B树和B+树之争
前置知识:知道mysql中索引即数据,数据即索引(页的存储结构);知道为何采用B树(多路平衡查找树),知道为何实际采用了B+树。
1,B+树空间利用率更高。B+树只在叶子节点存储实际数据,非叶子节点,B+树有了更多的空间存储索引,这样B+树越靠近矮胖,IO减少,
磁盘读写代价低,检索效率变高。
2,B+树查询效率更稳定。B+树的检索,任何检索路径都需要从根节点到叶子节点(只有叶子节点有数据),时间复杂度固定在O(LogN);
B树则在O(1)和O(LogN)之间。即二分查找。
3,B+树范围查询性能更优。 B+树的叶子节点使用了双向链表连接在一起,而且是严格的顺序存储,从左到右从小到大。
4,B+树由于叶子节点使用了链表进行串联,除了支持随机检索,还支持顺序检索。
一些常见概念
回表: 查询计划不是使用主键索引,即通过二级索引查找目标;而二级索引的B+树只存储了主键数据(索引列,主键),
如仍需要其它数据,需要再次根据主键去主键索引所在B+树查找一次数据的过程,即回表。
回表引发的问题:某些情况,使用了索引,但仍然触发了全表扫描(explain type='All')。因为此时查询优化器对比了回表IO次数和全表扫描的IO次数,选择了全表扫描。
MRR:MRR全称:Multi-Range Read Optimization(多范围读取优化),动机是减少随机磁盘访问的次数,实现对基表数据的更顺序扫描。
官网的解释在这。即把随机磁盘读转化为顺序磁盘读,提高查询性能(磁头运动&磁盘预读)。本质在做一件以空间换时间的事情。
下面这个图很形象借用一下:(红线表示查询路线,蓝线表示磁盘/磁头运动路线)
未开启MRR:

开启MRR:

上面的图来自文章MySQL的MRR到底是什么?
以空间换时间,这个空间指的是内存,内存大小设置在系统变量read_rnd_buffer_size,设置请参考官网。
使用SQL命令:SELECT @@optimizer_switch
查看MRR是否已开启(默认开启)

索引覆盖:查询目标可直接从叶子节点获取数据,不需要回表,即为索引覆盖。
如下图:country_id是二级索引,查找目标刚好只查询主键索引和二级索引键值本身,直接使用二级索引的B+树就能查到。不需要回表,称为索引覆盖。


最左匹配原则(多列索引): 官网的解释在这里。
举例:
有组合索引信息如下:

则验证的关键原则是:
-- 最左匹配原则要点:
-- 1,组合索引第一列(最左)作为第一个条件,只有接or不走索引,其它情况全部走索引;
-- 2,不以最左作为第一个条件,一般都不会走索引,唯有把组合索引条件都加上才会走(内部优化)。
explain select * from staff where first_name='Mike'; -- yes
explain select * from staff where last_name='Hillyer'; -- no
explain select * from staff where first_name='Mike' and last_name='Hillyer'; -- yes
explain select * from staff where last_name='Hillyer' and first_name='Mike'; -- yes(内部优化)
explain select * from staff where first_name='Mike' or last_name='Hillyer'; -- no
explain select * from staff where first_name='Mike' and(last_name='Hillyer' or last_name=''); -- yes
索引(条件)下推:即ICP,全称是Index Condition Pushdown Optimization,官网的解释在这里。我们一般叫索引下推,其实正式应该称为:索引条件下推。
怎么理解?下推什么呢? 顾名思义,Condition Pushdown,把查询条件往下推。官网的这句:
With ICP enabled, ... , the MySQL server pushes this part of the WHERE condition down to the storage engine.
翻译即是:ICP启用后,把where条件的部分从server层下推到storage engine层。
需要先了解MySQL的大概架构:

就是,原来where条件筛选在Server层这里,现在下推到存储引擎层去。
举例:
下表中,id是主键,name,age是联合索引。

查找姓张且年龄是10岁的记录:select * from tuser where name like '张%' and age=10;

没有使用ICP:二级索引找到主键1和4,分别回表去查找对应的完整记录,Server层再根据where条件的age=10进行筛选。这个过程要回表两次。
使用ICP: 二级索引找到主键1和4,存储引擎层(Server的下层)根据联合索引where条件age=10进行筛选。根据筛选结果再回表查到完整记录。这个过程回表1次。
上面的ICP举例和图片出自这里。
使用执行计划分析时,使用索引下推在Extra栏位会出现:Using index condition信息,具体参见。
MySQL默认启用索引(条件)下推。系统设置变量为:index_condition_pushdown

避免全表扫描:官网的解释在这里。
使用查询计划分析时,对于大型表,应尽力避免type=All的情况。 表扫描非常昂贵。
本文阅读MySQL文档为5.7。
下一篇继续探索索引优化部分。
MySQL-带你上官网看索引的更多相关文章
- MySQL入门(参考官网)
目录 一.登陆和退出 1. 远程主机 2. 登陆本机 3. 退出mysql 二.输入查询 三.创建和使用数据库 3.1 创建和选择数据库 3.2 创建表 3.3 将数据加载到表中 3.4 操作表格 3 ...
- jQuery layer弹出层插件 http://layer.layui.com/直接上官网学
在许多网站中,经常用到弹出层,有时候为了达到更好的用户体验,你将写繁琐的css跟js,这款 jquery-layer可以让你想到即可做到的web弹窗/层js组件.layer侧重于用户灵活的自定义,为不 ...
- 不再用上官网,自己部署一套ElementUI官方最新文档
ElementUI官方的访问速度一直很慢,公司内网也无法进行外网访问.故研究了下最新的ElementUI API(2.13.2)部署教程. 先上效果图 ElementUI文档部署过程 到github下 ...
- 跟着官网的例子学Reacjs (一)FilterableProductTable
最近开始学习React,发现最好的方法不是看这个书那个书,而是直接上官网,一步步的跟着学习,真的获益匪浅.许多翻译的书上漏掉的知识点都可以学到. 入门的一些准备工作可以参照官网的步骤,引入依赖的核心包 ...
- Knockout.Js官网学习(简介)
前言 最近一段时间在网上经常看到关于Knockout.js文章,于是自己就到官网看了下,不过是英文的,自己果断搞不来,借用google翻译了一下.然后刚刚发现在建立asp.net mvc4.0的应用程 ...
- 自建yum源解决Ceph搭建过程中从官网取包慢的问题
最近项目组需要ceph环境,第一次搭建ceph,各种不顺,装了卸,卸了装,一遍又一遍地按照官网的操作进行.最气人的是网速差,从官网取包太慢.一轮尝试就浪费一上午. 因此想到本地新建yum源. 首先,按 ...
- Flume Sinks官网剖析(博主推荐)
不多说,直接上干货! Flume Sources官网剖析(博主推荐) Flume Channels官网剖析(博主推荐) Flume Channel Selectors官网剖析(博主推荐) 一切来源于f ...
- 官网下载 Linux 上需要的 MySQL的步骤
1.输入MySQL 官网地址 https://dev.mysql.com/ 选择 download ->Community->MySQL Community Server 点击 MyS ...
- 1.JVM前奏篇(看官网怎么说)
JVM(Java Virtual Machine) 前奏篇(看官网规范怎么说) 1.The relation of JDK/JRE/JVM 在下图中,我们所接触的,最熟悉,也是经常打交道的 最顶层 J ...
- Spring官网阅读(十一)ApplicationContext详细介绍(上)
文章目录 ApplicationContext 1.ApplicationContext的继承关系 2.ApplicationContext的功能 Spring中的国际化(MessageSource) ...
随机推荐
- NodeJS - XSS-Attribute
参考:https://owasp-skf.gitbook.io/asvs-write-ups/cross-site-scripting-attribute-xss-attribute/kbid-3-x ...
- 12、jmeter逻辑控制器-临界区控制器
临界区:说白了就是不并发了 一个个的像独木桥 使用场景:比如提交一个数据 需要一个一个的提交 一个个的改 在数据库改操作的时候 需要用到 临界区控制器 案例:临界区控制器
- fetch请求方式
Fetch请求的方式 1:GET 请求 // 未传参数 const getData = async () => { const res = await fetch('http://www.xxx ...
- js实现切换页面清除定时器的函数
背景: 我在切换页面的时候,发现切换回原来的页面,定时器会叠加而不会清除原来的定时器 解决方法: 1.定义全局变量,通过js遍历清除(不会用,但性能好) var pageTimer = {} ; // ...
- 打不过AI就拉拢?ChatGPT和MidJourney已成我小秘书!
为了体验AI,晓衡这两周战斗力爆棚了! 每天大概睡了四~五个小时,而且中午也没有休息过,但精神却还很亢奋. 直到周一下午,身体才有种被掏空的感觉,晚上 10 点就睡了.可能是兴奋劲还在,早晨不到 6 ...
- 关于报出这样的错误:org.apache.catalina.core.StandardWrapperValve.invoke 在路径为/tt1016_war_exploded的上下文中,Servlet[Servlet.m的解决方法
从23:30开始报错检查,现在才弄好,发出来分享一下 错误界面: 首先,我们需要检查一下我们利用DBUtil.java文件中引用的db文件名称是否正确,(我就是因为没有注意到文件名称是否正确报出500 ...
- 从操作实例“UI界面实现SSH登录服务器并执行命令监控”中学习到的线程与线程间参数传递方法记录
从操作实例"UI界面实现SSH登录服务器并执行命令监控"中学习到的线程与线程间参数传递方法记录: https://www.cnblogs.com/babashi9527/p/165 ...
- Python——基础知识(一)
1. 那么多编程语言,为什么学python 易于学习,是所有编程语言当中最容易学习的 没有最好的语言,只有最合适的语言 2. 反复执行的用例如何提升效率 测试流程回归(回顾) 很多测试用例在不同的测试 ...
- 简述SpringAOP的实现原理
Spring默认采取的动态代理机制实现AOP,当动态代理不可用时 (代理类无接口)会使用CGlib机制. Spring提供了两种方式来生成代理对象:JDKProxy和Cglib,具体使用哪种方式生 ...
- AQS 锁核心类详解
系统性学习,异步IT-BLOG AQS(AbstractQuenedSynchronizer 抽象队列同步器) 是一个用来构建锁和同步器的框架,使用 AQS能简单且高效地构造出应用广泛的大量的同步器, ...