深入理解InnoDB(8)—单表访问

1. 访问方法

MySQL把执行查询语句的方式称之为访问方法或者访问类型。
而访问方法大致分为两类

  1. 全表扫描
  2. 索引
    而进行细分的话可以分为以下几类
    (为了方便说明,先建一个表)
CREATE TABLE single_table (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;

1.1 const

SELECT * FROM single_table WHERE id = 1438;SELECT * FROM single_table WHERE key2 = 3841;

例如上面两个sql语句,条件都是主键或者唯一二级索引列与常量进行比较

  • 第一个sql语句的执行,直接就是在主键的聚簇索引中,根据主键值进行匹配
  • 第二个sql语句,先要在对应的唯一二级索引中,根据查询的索引列进行一次匹配,查到主键id后,再回表查出所有的数据
    因为主键和唯一二级索引,他们的索引列都是唯一的,因此查找的速度是非常快的,所以这种访问方法叫const,意思就是常数级别的查询速度.(注意:当索引列的查询条件为空时,访问方法并不能算const,因为可能有多条记录为空)

1.2 ref

而ref的访问方式类似于唯一二级索引的访问方式,都是先在二级索引上进行匹配,找到主键id后,再回表查询。但是,因为普通二级索引列的值并不是唯一的,因此可能查询到的是多条记录,再进行多次回表。

SELECT * FROM single_table WHERE key1 = 'abc';

例如上面的sql语句,因为key1是普通二级索引,可能存在多个key1='abc’的记录,因此在查询时,需要对多个记录进行回表

1.3 ref_or_null

这个与ref类似,只是多了对于空值的匹配

SELECT * FROM single_table WHERE key1 = 'abc' OR key1 IS NULL;

例如上面的sql语句,是在key1这个二级索引上,查询key1 = 'abc’和key1为空的主键id,然后再进行回表

1.4 range

而range访问方法,意思就是根据范围进行查询,前面的查询都是匹配单个常数值的,而range是查询一个范围的。

SELECT * FROM single_table WHERE key2 IN (1438, 6328) OR (key2 >= 38 AND key2 <= 79);

例如上面的sql语句,只是在之前查询key2 IN (1438, 6328)的基础上,将满足79>=key2>=38的主键id也找出来,同样进行回表

1.5 index

SELECT key_part1, key_part2, key_part3 FROM single_table WHERE key_part2 = 'abc';

key_part2 = 'abc’这个条件并不满足最左匹配,但是key_part1, key_part2, key_part3 属于一个联合索引idx_key_part,因此这个查询是在idx_key_part索引的叶子节点中,一个一个匹配key_part2 = ‘abc’,直接返回索引列即可,并不需要回表。

index的意思就是直接在索引中匹配查询。

1.6 all

而all就是全表扫描

2.注意事项

2.1 一般情况下只能利用单个二级索引执行查询

SELECT * FROM single_table WHERE key1 = 'abc' AND key2 > 1000;

查询优化器会根据single_table表的统计数据,判断key1 = ‘abc’ 和 key2 > 1000两个条件,哪个索引查询的条数少,就选择到哪个索引的B+树上查。

例如在上面的例子中,优化器选择的是key1 = ‘abc’,那么查询到满足key1 = ‘abc’ 的主键后,就会回表查询,并且以 key2 > 1000为条件进行过滤

2.2 明确range访问方法使用的范围区间

2.2.1 所有搜索条件都可以使用某个索引的情况

例如:

SELECT * FROM single_table WHERE key2 > 100 AND key2 > 200;

因为条件都是来自同一个索引的范围查询,因此只要将对应的范围进行集合的运算即可

2.2.2 有的搜索条件无法使用索引的情况

SELECT * FROM single_table WHERE key2 > 100 AND common_field = 'abc';

因为common_field = 'abc’无法使用到索引,因此范围搜索只需要关注key2 > 100这个范围即可,回表的时候再根据common_field = 'abc’过滤一次,就可以保证选出来的记录满足 key2 > 100 AND common_field = ‘abc’。

SELECT * FROM single_table WHERE key2 > 100 OR common_field = 'abc';

但是,当条件换成or以后,就无法使用key2的索引了,因为查询出了key2 > 100的记录以后,没有办法也在key2的索引中查出common_field = 'abc’的记录

2.2.3 复杂搜索条件下找出范围匹配的区间

SELECT * FROM single_table WHERE (key1 > 'xyz' AND key2 = 748 ) OR(key1 < 'abc' AND key1 > 'lmn') OR(key1 LIKE '%suf' AND key1 > 'zzz' AND (key2 < 8000 OR common_field = 'abc')) ;

主要使用到key1和key2 两个索引,因此对他们进行分别的查找的区间

  • 对于key1
  1. 先将不属于key1的条件替换为true
(key1 > 'xyz' AND TRUE ) OR
(key1 < 'abc' AND key1 > 'lmn') OR
(TRUE AND key1 > 'zzz' AND (TRUE OR TRUE))
  1. 替换掉永远为TRUE或FALSE的条件
    因为符合key1 < ‘abc’ AND key1 > 'lmn’永远为FALSE,所以上边的搜索条件可以被写成这样:
(key1 > 'xyz') OR (key1 > 'zzz')
  1. 合并范围
key1 > xyz
  • 对于key2
  1. 先将不属于key1的条件替换为true
(TRUE AND key2 = 748 ) OR
(TRUE AND TRUE) OR
(TRUE AND TRUE AND (key2 < 8000 OR TRUE))
  1. 再次化简,可以推出最后条件是true,也就是说需要搜索全部的key2索引

2.3 索引合并

之前第一点注意事项说过: 一般情况下只能利用单个二级索引执行查询,而在特殊情况下也可能在一个查询中使用到多个二级索引。因此把这种使用到多个索引来完成一次查询的执行方法称之为:index merge,具体的索引合并算法有下边三种。

2.3.1 Intersection合并

Intersection(交集),意味着对多个二级索引的结果找交集

SELECT * FROM single_table WHERE key1 = 'a' AND key3 = 'b';

执行过程

  1. 在key1这个二级索引上找key1 = ‘a’
  2. 在key3这个二级索引中找key3 = ‘b’
  3. 因为二级索引查出来的记录格式是索引列加主键,因此直接对他们查出来的主键作一个交集再回表即可

为什么不直接查到二级索引key1的记录,然后在回表的过程中,过滤掉不满足key3的条件呢?

因为如果在key1上面查出来的记录条数很多的话,那么就要进行很多次的回表,而这种回表属于随机I/O,非常耗时,而选择两次的二级索引查找,属于顺序I/O,有更好的性能。

使用Intersection的情况:

  1. 二级索引只能是等值匹配
SELECT * FROM single_table WHERE key1 = 'a' AND key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';
SELECT * FROM single_table WHERE key1 > 'a' AND key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';
SELECT * FROM single_table WHERE key1 = 'a' AND key_part1 = 'a';
  • 第一条sql语句可以正常使用
  • 第二条使用了范围查询
  • 第三条没有使用联合索引的所有列
  1. 主键列可以是范围匹配
SELECT * FROM single_table WHERE id > 100 AND key1 = 'a';

因为二级索引下,索引列是已经排好序的了,而如果出现了索引列全部相同的记录,那么将按照主键值进行排序,而使用了排好序的主键来求交集,就非常简单了,因为对于两个已经排好序的主键序列,求他们交集的时间复杂度是o(n)。

这也回答了第一种情况,为什么只能是等值匹配,因为只有等值匹配的情况下,索引列记录相同的几条记录才能按照主键的顺序排好。

上面的两种情况只是使用Intersection的必要条件。优化器只有在单独根据搜索条件从某个二级索引中获取的记录数太多,导致回表开销太大,而通过Intersection索引合并后需要回表的记录数大大减少时才会使用Intersection索引合并。

2.3.2 Union合并

Union是并集的意思,适用于使用不同索引的搜索条件之间使用OR连接起来的情况。
使用Union的情况:

  1. 二级索引只能是等值匹配(与Intersection相同)

  2. 主键列可以是范围匹配(与Intersection相同)

  3. 使用Intersection索引合并的搜索条件
    例如:

SELECT * FROM single_table WHERE key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c' OR (key1 = 'a' AND key3 = 'b');

1.先按key1 = ‘a’ AND key3 = ‘b’,使用 Intersection得到一个交集

2.再使用 key_part1 = ‘a’ AND key_part2 = ‘b’ AND key_part3 = ‘c’,得到一个集合

3.再对上面求到的两个集合求并集。然后进行回表

优化器只有在单独根据搜索条件从某个二级索引中获取的记录数比较少,通过Union索引合并后进行访问的代价比全表扫描更小时才会使用Union索引合并。

2.3.3 Sort-Union合并

Union的条件太苛刻了,只有等值匹配才能使用到。

SELECT * FROM single_table WHERE key1 < 'a' OR key3 > 'z'

而对于这样的范围查询就无法使用了,而对于上面的sql就可能执行Sort-Union索引合并。

1.按照key1 < 'a’查出所有记录,并且排好序
2.按照key3 > 'z’查出所有记录,并且排好序
3.因为两个集合的主键都是排好序的了,因此直接按Union那样做就行了

为什么没有Sort-Intersection?
因为Union是在单独根据搜索条件从某个二级索引中获取的记录数比较少的情况下使用的,而这种情况下记录数少,排序的性能损耗小。而Intersection的情况恰恰相反,它是针对查询出的记录数多,如果排序对于性能的损耗就很大了

2.3.4 联合索引注意事项

联合索引替代Intersection索引合并

SELECT * FROM single_table WHERE key1 = 'a' AND key3 = 'b';

像这样的sql语句,需要使用到两个单独的索引,倒不如直接做成联合索引,既可以少一颗b+树,还不能做集合运算。

ALTER TABLE single_table drop index idx_key1, idx_key3, add index idx_key1_key3(key1, key3);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蝙蝠侠遥控器pcb_通过蝙蝠侠从Circle到ML:第二部分

蝙蝠侠遥控器pcbView Graph查看图 背景 (Background) Wait! Isn’t the above equation different from what we found last time? Yup, very different but still looks exactly the same or maybe a bit better. Just in case you are wondering what I am talking about, p…

camera驱动框架分析(上)

前言 camera驱动框架涉及到的知识点比较多&#xff0c;特别是camera本身的接口就有很多&#xff0c;有些是直接连接到soc的camif口上的&#xff0c;有些是通过usb接口导出的&#xff0c;如usb camera。我这里主要讨论前者&#xff0c;也就是与soc直连的。我认为凡是涉及到usb的…

工程项目管理需要注意哪些问题

在社会科学技术发展和市场经济繁荣昌盛的今天&#xff0c;为更好的满足社会人性化的需求&#xff0c;建设施工企业在建筑施工、布局以及内部运行都给予了落实。而工程项目是建筑施工企业面向建筑市场的窗口&#xff0c;是企业建筑活动的前沿阵地&#xff0c;管理需更严谨。 虽说…

leetcode 872. 叶子相似的树(dfs)

请考虑一棵二叉树上所有的叶子&#xff0c;这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。 举个例子&#xff0c;如上图所示&#xff0c;给定一棵叶值序列为 (6, 7, 4, 9, 8) 的树。 如果有两棵二叉树的叶值序列是相同&#xff0c;那么我们就认为它们是 叶相似 的。 …

探索感染了COVID-19的动物的数据

数据 (The data) With the number of cases steadily rising day by day, COVID-19 has been pretty much in the headlines of every newspaper known to man. Despite the massive amount of attention, a topic that has remained mostly untouched (some exceptions being …

Facebook哭晕在厕所,调查显示用VR体验社交的用户仅为19%

美国娱乐软件协会ESA调查显示&#xff0c;有74%的用户使用VR玩游戏&#xff0c;而仅有19%的用户会用VR进行社交。 当我们说到VR社交&#xff0c;必然离不开Facebook。在刚刚结束的F8大会上&#xff0c;小扎展示了VR社交平台Facebook Spaces测试版&#xff0c;巧的是此前也有好…

网页自动刷新

eg1&#xff1a;<meta http-equiv”refresh” content”4” /> 间隔4秒网页自动刷新 eg2&#xff1a;<meta http-equiv”refresh” content”8;http://www.baidu.com” /> 等待8秒自动跳转到百度页面转载于:https://www.cnblogs.com/zwtqf/p/7667774.html

解决Javascript疲劳的方法-以及其他所有疲劳

Learn your fundamentals, and never worry again. 了解您的基础知识&#xff0c;再也不用担心。 新工具让我担心 (New Tools Worry Me) When JavaScripts shiny tool of the day comes out, I sometimes overreact. 当JavaScript一天一度的闪亮工具问世时&#xff0c;我有时R…

Java 8 的List<V> 转成 Map<K, V>

问题&#xff1a; Java 8 的List 转成 Map<K, V> 我想要使用Java 8的streams和lambdas转换一个 List 对象为 Map 下面是我在Java 7里面的写法 private Map<String, Choice> nameMap(List<Choice> choices) {final Map<String, Choice> hashMap new…

已知两点坐标拾取怎么操作_已知的操作员学习-第4部分

已知两点坐标拾取怎么操作有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as mu…

北京供销大数据集团发布SinoBBD Cloud 一体化推动产业云发展

9月5日&#xff0c;第五届全球云计算大会在上海世博展览馆盛大开幕&#xff0c;国内外顶尖企业汇聚一堂&#xff0c;新一代云计算技术产品纷纷亮相。作为国内领先的互联网基础服务提供商&#xff0c;北京供销大数据集团(以下简称“SinoBBD”)受邀参加此次大会&#xff0c;并正式…

windows下有趣的小玩意

1.显示文件和隐藏文件。在当前目录下shift右键 选择cmd命令 运行显示文件: attrib -s -h 文件名 隐藏文件: attrib -s h 文件名 2.查看电脑支持的最大内存 在cmd下运行wmic memphysical get maxcapacity所得结果单位mb 所得/1024/1024 得到单位G 3.windowsR 输入…

rxjs angular_Angular RxJS深度

rxjs angularIn this tutorial, well learn to use the RxJS 6 library with Angular 6 or Angular 7. Well learn about:在本教程中&#xff0c;我们将学习将RxJS 6库与Angular 6或Angular 7结合使用。我们将了解&#xff1a; How to import the Observable class and the ot…

HashMap, LinkedHashMap 和 TreeMap的区别

HashMap, LinkedHashMap 和 TreeMap的区别 Java里面的HashMap, LinkedHashMap 和 TreeMap 有什么区别?我看不出以下3个key和value有什么不同的。Hashtables里面又是怎么样的呢&#xff1f; Map m1 new HashMap(); m1.put("map", "HashMap"); m1.put(&q…

“陪护机器人”研报:距离真正“陪护”还差那么一点

一款有“缺陷”的机器人&#xff0c;怎能做到真正的“陪护”&#xff1f; 近日&#xff0c;鼎盛智能发布了一款名为Ibotn的&#xff08;爱蹦&#xff09;幼儿陪伴机器人&#xff0c;核心看点就是通过人脸识别、场景识别等计算机视觉技术来实现机器人对儿童的陪护。不过&#xf…

neo-6m uno_Uno-统治所有人的平台

neo-6m unoFirst, we should start off with what Uno is and why you should care. 首先&#xff0c;我们应该从Uno是什么以及为什么要关心开始。 As stated on their website, Uno is "The only platform for building native mobile, desktop and WebAssembly apps wi…

【转】消息队列应用场景

一、消息队列概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量削锋等问题。实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。 目前在生产环境&#xff0c;…

JDK和JRE区别是什么

问题&#xff1a;JDK和JRE区别是什么 他们的角色分别是什么&#xff1f;我们应该什么时候使用他们&#xff1f; 回答一 JRE是Java Runtime Environment&#xff08;Java运行时环境&#xff09;。它是一个包&#xff0c;集合了运行一个编译好的Java程序的一切必须的东西&…

树莓派新手入门教程

http://www.ruanyifeng.com/blog/2017/06/raspberry-pi-tutorial.html

lime 模型_使用LIME的糖尿病预测模型解释— OneZeroBlog

lime 模型Article outline文章大纲 Introduction 介绍 Data Background 资料背景 Aim of the article 本文的目的 Exploratory analysis 探索性分析 Training a Random Forest Model 训练随机森林模型 Global Importance 全球重要性 Local Importance 当地重要性 介绍 (Introd…