众所周知, MySQL的驱动表与被驱动表是优化器自动优化选择的结果 (与表连接的前后顺序等无关),我们可以用explain执行计划来知晓:
如上所示,前面一行t1是驱动表,后面一行t2是被驱动表。那么驱动表与被驱动表的选择是否有规律可循呢?下面是百度搜索两个主流的博文对驱动表与被驱动表的阐释:
1. MySQL连接查询驱动表被驱动表以及性能优化 - 阿伟~ - 博客园 博文A 主要结论:
2. mysql驱动表与被驱动表及join优化_java小小小黑的博客-CSDN博客_mysql驱动表和被驱动表 博文B 其主要结论:
两个帖子的结论是都差不多,而且还给出了例子来佐证。那么网上的结论是否权威?是否有普遍性?是否存在缺陷?
让我们来一起打破砂锅问到底。下面有两张表结构一模一样的表t1,t2:其中t1 100条数据,t2 1000条数据;t1(t2)结构如下:
按照上面博文的结论,left join左边是t2表,应该是驱动表。我们查看下结果:
与 博文B 中观点1相违背(同理观点2也违背),与实际不符,但究竟这是为什么呢?
下面发一张MySQL的执行过程(来源于《MySQL实战45讲》中01讲【一条SQL查询语句是如何执行的】)
so die si ne,原来sql执行的过程是这样呀。等等,不对,这跟刚才SQL又有什么关系,上面left join中t2表还是左边的呀。
我们知道MySQL高版本的性能越来越好,它是不断进行优化迭代的。远古的mysql版本可能还需要人工把小表放在前面,大表放在后面等这些需要人工调优的经验早就已经被解决了。也就是说我们写的语句,MySQL为了追求更好的效率,它在执行器执行前已经帮我们优化了。那么实际优化后的sql如何查看呢?用show warning命令:
其中Message就是优化后实际执行的sql语句,格式化后如下:
优化后left join左连接变成了内连接(inner) join。所以用优化后的sql看,表t1是小表所以作为驱动表,与实际结果相符。
left join 竟然优化成了join,太神奇了,但这是为什么呢?原因在于mysql中null与任何值做等值或者不等值比较的时候都是null,即使是select null=null 也是null。这样where 条件t1.a=t2.a查询条件不会包含t2.a为NULL的行,实际效果其实跟join一样,被优化器智能的优化了。
我们直接看执行计划看实际结果吧:
结果显示t2是驱动表,t1是被驱动表。t2是1000条数据按理说是大表应该是被驱动表,与 博文A , 博文B 的结论又不一致了。
《MySQL实战45讲》中34讲【到底可不可以使用join】已经讲的很透彻了,很深入了,我就不在这里献丑了。啰嗦几句大概就是驱动表是全表扫描不走索引,所以选被驱动表t1可以走索引,不会全表扫描,减少IO次数,性能高。里面对大表小表的总结,简直是精髓,特意在此再次着重强调:
在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与join的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。
按照上面分析,我们先独立思考下MySQL会选择哪张表作为驱动表呢?
表t1,t2在字段a上都有索引不会全表扫描,其中t1.a=5条件过滤后只有一条,很显然嘛,t1数据量少是小表,肯定是驱动表,错不了,再说了前面的红色粗体已经强调了,不会有错的。
有冇搞错?事实又被打脸了。还记得在开篇我们说过的mysql优化器会对sql语句进行优化的吗?下面我们看下执行计划与优化的sql语句:
格式化后的优化SQL如下:
优化后两表t1,t2都走索引,并且都只有一条结果返回,因此都只会扫描一行,数据量一样,所以谁在前面谁就是驱动表,也就是上面sql中表t2。一切都释然,豁然开通!
回头再仔细想想,高,实在是高!仔细深思之后MySQL优化后的句子真让人猛拍大腿。高明之处在于:
1. 本来join连接是个M*N的嵌套循环,优化后变成了M+N的判断,两表不再嵌套判断了。
2. 优化后,两表没有多大必然联系,只需把两表的结果集拼接即可,互不干扰。如果mysql未来可以多线程查询,岂不十分快哉!
小伙伴们还记得我们在上一章 MySQL索引初探 中编码类型不一致发生隐式转换时有时候走索引,有时候索引又失效的问题吗?下面我们选取有代表性的一条记录来分析:
其中表demo_test总共有640条数据,demo_test_ass有3条数据。显然经过过滤条件t.rid>1完成后demo_test_ass数据量小,应该作为驱动表。虽然test.c_utf8mb4 = t.c2两字段连接中发生了t.c2字段发生隐式转换,但是实际上并不影响被驱动表test上的c_utf8mb4索引。
好了,本章到此结束,让我们一起 总结一下MySQL驱动表与被驱动表的选取原则 :
หน ง 同等条件,优先选取有索引的表作为被驱动表。 在此介绍一下什么叫同等条件,比如上面的②中的语句。 两表没有其他额外的过滤条件,因此选关联字段有索引的t1作为被驱动表。但是如果加了条件(and t1.id=3),此时t1数据量少,就选取了t2作为被驱动表。
สอง MySQL选择驱动表与被驱动表是基于优化器优化后的,小表是驱动表,大表是被驱动表。 基于优化器优化后开篇的 博文A与B 结论成立。
当然这都是我一家之言,并不是官方结论,目前暂未找到官方确切对于驱动表与被驱动表的解释,请大家踊跃拍砖!
你好呀,我是why。
刚刚过去的周末你干啥了,是卷起来了,还是躺平了?
我其实是想躺平的,但是无意间发现一个学习的网站,居然被这个网站吸引了,然后就跟着网站卷起来了。
真是一个非常不错的网站,好东西,要大家分享,于是我决定“曝光”一下。
介绍这个网站之前,我先问你一个问题:
我相信绝大部分同学都是知道的,但是也有很大一部分同学仅仅是在“纸上谈兵”的阶段而已。
没有自己实际 *** 作过。
为什么呢?
我猜你刚刚知道 Arthas 的时候,肯定是被它各种炫酷的 *** 作、页面给吸引到了。
心想:卧槽,这么 6?
兴致勃勃的准备实 *** 一把,结果一看:需要自己搞个 Demo ,把 Demo 扔到服务器上运行起来,然后在服务器上安装 Arthas,才能分析。
这一套 *** 作对于大部分人来说是没有啥问题的。
但是还是有相当大的一部分同学,都没有一个属于自己的服务器。
巧妇也是难为无米之炊的呀。
第一步就被卡的死死的。
有心实 *** ,奈何条件有限。
于是这事就被搁浅了,放着放着,由于自己没有实 *** 过,关于 Arthas 的各种骚 *** 作也就忘的差不多了。
没有一个趁手的 Demo,没有服务器,没有一个安装好环境的服务器。
这种问题经常出现,也算是学习中遇到的“最后一公里”的问题。
我碰到的这个网站,就是为了解决“最后一公里”这一问题的。
也许它还不够完善,但是至少在 Arthas 上的支持已经是属于无可挑剔了,真正的手摸手教学。
铺垫了这么多,那么网站是啥呢?
就是下面这个网站:
知行动手实验室,是阿里旗下的阿里云弄出来的云原生开源技术体验平台。
它自带运行环境。
使用者只需要关心教程内容本身,无需为繁琐的运行环境准备工作浪费时间。所有实验都在一个事先准备好运行环境的容器中运行。
它具有沉浸式学习体验。
集交互式文档、终端、编辑器三个窗口于一个浏览器页面,无需在多个窗口来回复制粘贴。
它可以一键自动执行命令、代码自动修改。
文档实时可交互,通过鼠标点击即可一键自动执行命令、代码自动修改等 *** 作;也可以选择在终端、编辑器内手动输入查看效果。
我知道,这里的画风看起来很像是一个广告。
但是我发誓,我真的是自来水,真心推荐。
知行动手实验室,看这个名字就知道强调的是“行知合一”,是“动手”。
我曾经看到过阿里的一篇名叫《我看技术人的成长路径》的文章。
但是实际情况呢,我们不得不承认,大家自学占据了相当大的比重。
而大家自学的时候都有一个通病就是:只看、只想,基本不动手。
关于动手,我印象最深的就是我看这本书的时候:
我记得看这本书的时候,是我刚刚毕业一年多的时候。
当时觉得技术书还挺贵的,还是和同事一起合买的,一人出一半的钱,书放在办公室大家一起看看。
我那个时候一有时间就去翻翻这书。
第一次看的时候感觉:哇塞,这真是一本好书啊。里面全是我不知道的知识点。
但是看完之后,没隔多久,遇到一个问题然后想了半天:呃,这个问题书上好像讲过啊,怎么就想不起来了呢?
于是我就问同事:你是怎么看这个书的呀?我前段时间把书每一页都翻完了,但是现在好多东西都想不起来了。
他告诉我:首先得多看,书中的信息量对你来说还是太大了,看一遍吸收不完全是很正常的。还有,书里面的这么多动手 *** 作的实例,你跟着敲了没?我都 *** 作了一遍,遇到了各种各样的坑。印象自然而然的就深刻了一点。
可谓是一语点醒梦中人,我确实是没有实 *** 过。
不仅没有实 *** 过,甚至一看到实 *** 部分的具体命令,我都是几眼就瞟完了,因为我觉得这部分不重要。
后来我又看了一遍,看这遍的时候,我搞了几个服务器,就跟着书上,把上面的命令都敲了一遍。
进度慢了很多很多,但是吸收的东西也多了很多很多。
过去这么几年了,时至今日,我都记得周末的时候我跑到公司去翻这本书的场景。我都记得我跟着书上搭建集群的时候遇到的各种各样奇奇怪怪的问题。我都记得那 16384 个槽,还有那我怎么也运行不起来的 redis-trib.rb。
我都记得几年以后的一次,面试官问我:你了解 Redis 的集群吗,你自己搭过集群吗?
我当然记得了,毕竟之前那个只有一年经验的小伙子硬着头皮搭集群的时候,心态都被搞崩过数次。
还有近段时间断断续续在看的《MySQL实战45讲》、《MySQL是怎样运行的》、《高性能MySQL》。
里面其实都有大量的实例,特别是 45 讲,好东西呀,老师全是基于案例去讲的。
我看的时候也看的很慢,反正不管懂不懂,先动手开几个窗口,然后把实验的 SQL 准备好,跟着老师一步步的来。
总之,就是要动手。动手,才是学习新技术的不二法门。
做中学,就是动手去做,边做边学。
但是动手的时候大多数时间都是在环境的准备上,导致效率稍微有了那么一点点的低下。
而这个网站,就在部分项目上,解决了这个问题。
回到知行动手实验室,带大家一起逛一下这个网站。
说真的,目前这个网站的东西不算特别多,也就是花费了我一个周末的时间研究了一圈。
主要是里面还有一些我不太了解的开源项目,去了解了一下,开拓了一下眼界。
主打的都是阿里生态下的一些技术栈,目前一共有 16 个教程:
可以看到,首先映入眼帘的就是 Arthas 这个诊断工具,毕竟是阿里的亲儿子中比较有出息的一个嘛。
全力推广,不过分。
Arthas 其中分为了四个教程,从入门到实践一应俱全。
接着是 Spring Cloud Alibaba 系列体验:
里面的六个小实验,其中分布式配置、服务注册与发现都是基于 Nacos 做的。 RPC 调用使用的是 Dubbo Spring Cloud、限流与熔断基于 Sentinel、分布式事务使用 Seata、分布式消息基于 RocketMQ。
基本涵盖了微服务开发的主要模块。
算的上是一次完整的体验。
当然了,还有一些其他的 RocketMQ、Dapr、Dubbogo、ChaosBlade、k8s 的实 *** 教程,就不一一解释了。
大家知道目前里面有这些东西就行。
上面提到的大家可能对于 Dapr 和 ChaosBlade 稍微陌生一点。
简单的说一下。
Dapr 的全称是 Distributed Application Runtime,翻译过来就是分布式应用运行时。
它主要是为了云原生而服务的。
应该是属于服务网格中的一种技术,是一种运行时,支持k8s,目的是为了更好的隔离业务,让业务更少的感知中间件等基础建设。
其实与它对标的,应该就是 istio 架构。
需要注意的是 Dapr 是由微软发起的一个开源项目,并不是阿里。
阿里是 Dapr 开源项目的深度参与者和早期采用者,相当于是对于 Dapr 的一个国内大厂背书。
而 ChaosBlade 就是阿里巴巴开源的一款遵循混沌工程原理和混沌实验模型的实验注入工具,帮助企业提升分布式系统的容错能力,并且在企业上云或往云原生系统迁移过程中业务连续性保障。
引用其 git 上的描述:
该项目的生态如下:
目前支持这么多场景:
比如在知行动手实验室里面就有三个实验场景:
总之,关于 ChaosBlade 你就记住一句话:
它是来搞破坏的。给系统或者系统运行的环境注入各种各样的故障,以测试并提升系统的稳定性和高可用性。
在知行动手实验室里面,除了前面提到的官方教程外,它还支持大家自己上传教程。
下面这几种情况就很适合在上面发布教程:
你想想,要是我前面提到的《Redis开发与运维》书里面的随书实验能发布到这里,那岂不是美滋滋?
学习效率肯定又高了起来。
教程,是该实验室的一大核心功能。
但是,它还有另外一大功能:
Java 工程脚手架,下面的标语是:
更适合亚太区开发者的 Java 工程脚手架。
虽然我目前还不明白为什么是“更适合亚太区”,但是反正听着就很厉害的样子。
其页面是这样的,是不是很眼熟?
一看就是对标的大家更为熟悉的这个:
但是通过我的实际使用,我不得不说,还是阿里的脚手架更好用一点。
比如我用阿里的脚手架,搭建的时候选择一个 web 项目的示例代码:
该项目结构如下:
而且这个 web 项目不需要改一行代码,甚至不需要你启动数据库,就能直接运行起来。
因为其使用的 h2 数据库:
运行起来后,访问 h2 控制台如下:
虽然 Demo 项目运行的过程中我发现了几个 bug,但是整体无伤大雅,修改起来也很简单,对于初学者来说,还是很友好的。
在这个页面我还发现了一个叫做 COLA 的项目架构:
COLA 是啥玩意?
我在官网上拉了一个 COLA 的 Demo,跑了起来,项目结构如下:
官方给了这样的一个代码结构图:
看到这里的时候,我大概明白了,有 App 层、Domain 层、 Infrastructure 层,这个架构其实就是 DDD 思想的一种落地吧。
经过这两天短暂的了解,我发现如果想要理解一下抽象的 DDD 思想,那么 COLA 架构,我感觉是一个不错的切入点。
前面介绍了这么多东西,我还是来带着你实 *** 一把,里面的黄金教程:
其实我觉得真的没有这个必要,因为它上面的教程已经是一步步的手摸手教学了。
比如,你看这个 Arthas 基础教程,我给你录个屏幕:
左边是 *** 作文档,右边是运行环境。所及即所得,多香啊。
我是强烈建议你把四个教程都自己去看一遍, *** 作一把。
但是重心可以放到这个教程里面:
你看看这个教程里面的 14 个实验:
比如其中的“Arthas热更新代码案例”,这个其实就是一个生产环境常常会遇到的一个问题:
有一个判断逻辑有问题,我不想修改代码之后,重新打包,然后走上线流程,怎么办?
Arthas 热更新了解一下?
比如,下面的代码:
现在当请求的 id 小于 1 的时候会抛出异常。但是上线之后,我们经过评估发现这个地方也许返回一个默认的值,不抛出异常会更好一点。
那么我们就可以用 Arthas 对这段代码进行热更新。
左边是修改之后,右边是修改之前:
具体怎么去修改,怎么去用 ClassLoader 加载修改之后的代码,这个案例里面都有详细的使用说明:
当然了,如果你要是在实 *** 之后,又再去了解了其热更新背后的工作原理,那么是再好不过的了。
知道了使用方式,掌握了实现原理。恭喜你,再给自己的套一个生产案例,不经意间面试的时候有多了一个加分点。
另外,悄悄的说个骚 *** 作。
你可以随便找个教程,领个窗口,然后......
比如我装个 Redis:
用起来也是不错的:
而且它也支持文件的上传和下载:
诶,反正就是玩嘛。就当熟悉 Linux 命令了。
前言
案例取自极客时间《mysql45讲》
案例
模拟执行器分析查询语句
场景复现
奇了怪了,此时没用索引,进行了全表扫描
虽然使用了索引,但是还是扫描了37116行,不妨结合之前的知识分析一下:
1.另一个事务未提交,需要保存之前的数据的数据版本,因此delete10万行数据实际是标记数据,这样每一行数据就有两个数据版本,旧的是delete之前的,新的是标记为delete的,索引a上的数据有两份
2.那还多出来的1万7呢,之前介绍过索引树的叶子节点存的是主键,select * 还要进行回表查询,这里将回表的扫描行数一并算上
为什么会选错索引
选择索引是优化器的工作,优化器要找到最优的执行方案并选择最小的代价去执行,扫描行数是影响执行代价之一(扫描越小,访问磁盘次数越少,消耗CPU资源越少)
mysql执行语句之前需要通过根据信息来统计记录数
这个统计信息就是索引的区分度,即索引上不同的值越多,区分度越高越好(show index t 的 cardinality字段查看),索引的区分度是利用采样统计得到的即取小部分统计信息再乘以整体。
除了使用统计信息,还会计算回表代价(主键不需要回表)
如果是统计信息不对那就修正
另一种场景复现
按理说这是个空集,利用索引a只扫描1000行,利用索引b要扫描50000行,这里优化器竟然选择了索引b!!
mysql又选错了索引
解决办法
2.引导使用a索引
我们知道索引树上的数据是有序的,优化器使用b索引,一方面是认为索引b可以避免排序 ,order by a,b强制按照a,b排序意味着两个都需要排序,因此扫描行数成了影响决策的主要条件
3.删掉索引b
解决mysql选错索引主要有两大方向
1.强制指定索引
2.干涉优化器选择(比如增大limit数量,增加order by ,写成子查询)
MySQL选错索引导致的线上慢查询事故
mysql中走与不走索引的情况汇集(待全量实验)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)