00:00
好,同学们,咱们接着往下讲啊,下边呢,我们要谈谈叫照样语句的一个原理,什么意思呀,你看咱们刚才呢,是不是通过一些SQL语句的一些呃,运行演示,通过这些现象呢,我们得到了对应的一些结论,那这个结论是什么呢?我们稍微的再去总结一下,通过这个A表呢,我们去连接这个B表,连接的条件呢,我们是A表的A字段和B表的这个B字段,那如果说呢,这个AB这两个字段呢,都没有索引,那这时候我们说结论呢,叫做小表来驱动大表,对吧?那么什么叫小,什么叫大,咱们先泛泛这样一说,咱们在这一节里边呢,会给大家明确下来。OK,小表驱动大表,那么在这个基础之上呢,如果说我们这个B表中的B字段呢,有索引了,那这时候呢,我们是不是这个B呢,就一定是作为这个被驱动表来出现的,那反之的话呢,如果说他俩都没有索引的情况下呢,A这时候呢,有索引了,那这时候A是不是就作为这个被驱动表来出现了。啊,没有问题。好,那么在我们这个B字段有索引的情况下呢,A字段呢,也有了索引呢,那这呢又回归到呢,就是我们叫小表来驱动大表这样一个场景。
01:00
行,这呢是通过我们刚才这个现象呢,咱们得到的这个结论,那么现象到结论中间呢,影响的是谁啊,就是我们这叫查询优化器,那优化器呢,它为什么要这样去做呢?那我们现在呢,是不是要呃去分析它呀,那目前的这个产液化器对于我们来讲呢,还像是一个黑盒子,那我们现在就要把它剥离开,我们看看里边支撑的数理逻辑是什么。啊,就好比是呢,大家这个中学的时候呢,学习化学,当然了,咱们学习化学的时候呢,其实已经经过好几代化学人的一个积累了,已经是一门科学了,那么在这个几个世纪之前的时候呢,当然咱们现在学的这些化学啊,物理啊,其实都是西方的自然科学的体系,他们搭建起来的,咱们现在学的主要其实都是一个细化的一些内容,对吧,那么这个欧洲的一些贵族呢,家里比较有钱,买了一些瓶瓶罐罐的一些这个呃,实迹是吧,然后呢,就开始来回倒腾啊,这个看看这个现象是什么啊,得到一些什么样的结论,那么这种情况往前去推进的话呢,其实化学呢,也很难有一个长足的一个发展,那后期的话呢,呃,要想化学呢,作为一个学科固定下来,那这时候呢,还得需要呢,研究相关的一些理论啊,那这呢,是不是就深入到这个微观层面了,那一个历史性的事件呢,就是俄国的,这叫门捷列夫,是不是发现了叫元素周期表啊,OK,那么有了元素周期表的一个支撑之后呢,化学咱们就是中学学的,呃,很多这个不管是世界也好,这个固态的东西也好,是不是都有一些。
02:22
呃,公式了是吧,我们谁加谁酸加,呃,这个碱等于这个盐是吧,等等这样的一些情况就出现了,那么这个时候的话呢,化学呢,就可以作为一门科学来出现啊,不断的去往前发展和推进了,那我们现在要做的事呢,其实就在研究一下刚才这些现象,底层支撑的物理数理逻辑到底是什么,就是我们现在要讲的这个照样的一个原理。好,那么这里边呢,就提到了一个算法,叫做next loop转啊叫NL接啊叫嵌套循环算法,OK,行,那么在讲这个之前的话呢,首先我们再把这个概念呢来明确一下,就是驱动表和被驱动表,也就是说呢,刚才不是已经讲到了吗?其实我们还没有说透彻,下边我们把它透彻的说出来,驱动表和被驱动表从我们这个查询的结果上来看,我们上边这个它就一定是驱动表,下边这个呢,一定是被驱动表,这点的话呢,大家要明确了。
03:15
就是我们所谓的驱动表,被驱动表,实际上呢,是从我们查询优化器呢,它优化完以后的这个explain的这个结果上看到的,上边呢是驱动,下边是被驱动,好那么基于这样场景场景的话呢,我们来说一下,如果我们是一个内连接A转B,那么A一定是驱动表吗?啊这个呢,我们要说啊,不一定是吧,不一定,我们结论不是说了小表驱动大表吗?你要这个B呢,是一个小表的话呢,是不是B就作为驱动表出现了。啊,没有问题是吧?好,这是一个事儿,然后呢,对于我们这个Y连接来讲啊,我们说有阻碍连接右外连接,好首先呢,我们这样来看啊,这个a left join b跟这个B呢,Right join a,仅仅从这个字面上来看的话呢,如果查询优化器呢,没有帮我们去改这个顺序,那么此时的话呢,我们可以说呢,A呢相当于是一个驱动表的一个位置,B呢,相当于是个被驱动表的位置,那么对于这个呃外连接来讲,这个差异化器会帮我们去修改它们俩的一个位置嘛。
04:14
啊,内连接咱们说了会的是吧,那外连接会吗?哎,其实也会的,这呢我为了验证这个事呢,专门呢写了一个例子,咱们先把这个概念呢说清楚好回过来这呢,呃,我们把这个事呢先写一下啊照样的一个,哎,底层原理。好,那我呢,转过来。啊,这个保存一下,那这时候的话呢,我们在这个艾特硅谷DB two啊这样的一个数据库下呢,我们创建两张表,一个叫叫A呢叫B行,首先呢,我们创建一下。没问题,创建完成以后的话呢,我分别往这个A和B这两个表里边呢,去添加一些数据,这个就比较简单。嗯,可以了是吧,啊这个呢,就看不看这个都行了,行,这个我就删掉吧,那么接下来的话呢,我们去做这个对应的这个测试,但是你看我此时的话呢,是不是用的这个叫外连接了,OK,然后呢,这是一个关联的一个字段,这加了一个过滤的条件,好选中以后呢,我们做个执行,大家看,明明我们这里边写的是a left join b啊当然我们这个结果当中呢,是不是先有B后有A,那就说明呢,我们这个B呢,是不是作为了叫驱动表,A是不是作为了叫被驱动表出现的呀。
05:17
啊,这下呢,下边呢,我相当于又写了一个条件,这个里边的话呢,A就作为这个驱动表出现的,那也就是说呢,我们对于外连接的表呢,也并非说前面这个就一定是驱动表。啊,那么这个真实的情况是什么呢?呃,这个呢,我看了看这个禅液化器呢,帮我们改造以后的这个S口语句到底是什么,实际上的话呢,它帮我们把这个外连接改造成了一个内连接,那既然呢已经变成内连接了,那我们说呢,谁作为驱动,谁作为被驱动化呢?差异化器呢,是不是就自己说了算了,OK,那么你要是整体上来看的话呢,你也可以说啊,这个对于外链接来讲呢,前面这个不一定是驱动表。啊,知道这个事儿就OK了,行,那如果说我把这个呢,直接啊这个我我再测试一个,咱们说一下那个内连接这个事儿是吧,比如我把这块呢粘过来,把后边这个呢先留着吧,把这个呢我们先干掉。
06:07
没问题是吧,好,此时的话我们做一个选中执行。但是你看这呢,是我们一个内连接A撞B,当然这个里边呢,是不是先有B后有A啊相当于呢,就是我们对于内连接来讲的话呢,哎,就相当于电脑了啊这呢是我们这个测试三。没问题啊,我要说的这个点呢,大家应该都听明白了,那么接下来的话呢,我们来谈一谈这个底层的一个原理,首先的话呢,我们说一个比较简单的叫simple的这个NLG啊,叫简单的嵌套循环连接。呃,这呢是什么情况呢?哎,就是我们谈到这个照样操作啊,其实本质上本质上来讲的话呢,其实就是一个循环匹配。啊,大家呢,对于循环应该都比较了解,对吧?那我们现在呢,这个A表呢,去连接B这个表,然后呢,A表中的字段呢是A,然后B表中的字段呢是B,啊现在呢,连接我们对应的这个,呃,这个数据一行一行的,那我们从这个驱动表里边呢,取出一条数据,然后呢跟我们这个叫被驱动表也行,叫非驱动表也可以。
07:05
跟我们这个被驱动表里边每一条记录呢,一条一条的去做连接,此时注意A和B呢,都没有任何的索引啊,就是非常干净的纯粹的这样的两个普通的表。OK,就这样连,这样连的话呢,是不是就是一个全表的一个便利了啊,来一条数据全表变了一遍,来一条数据全表变了一遍,好,那么这个时候的话呢,我们说如果A表中呢,有100条数据。当然这个呢,呃,咱们还得加个条件啊,就是select,然后呢from,然后John,然后啊注意还有个where呢是吧,这个where过滤完以后,不管你是针对A表啊B表啊,过滤完以后,A呢是有100条,B呢是有1000条,是这个意思,那么此时的话呢,我们到底要查询多少次呢?那这个时候呢,是不是就A乘以B就行,100乘以1000,一共呢是10万次,那在这个过程当中的开销是什么样子的,我用这个符号来表示呢,叫simple的这个NLG。好,那外表扫描的次数,我们是不是就整个呢,全扫描一遍,那就属于一次啊。
08:01
那么内表扫描的次数呢?我们来一个这呢扫描一遍,来一个扫描一遍,扫描多少遍是不是呢?就是我们A表中的这个条目数,我用这个A呢来表示的就是这个100了,B呢来表示的就是这个1000 OK,那么我们读取的记录数是多少呢?我们A表中呢,是不是一个一个的都读一遍,一共呢?是不是就A个呀?那么B表的话呢,A来一个B呢,是不是就得读一个叫B啊,再来一个有个B是不是就A乘以B好,所以呢,加一起就是我们读取的这个记录数,那照比较的次数呢,这来一条记录呢,是不是来一遍来一条记录来一遍是不是就B乘以A就可以了,或者A乘B一个意思,那这呢,因为不涉及到我们有这个索引的情况,所以没有回表这个概念,行这呢就我们说这样一个成本,那很显然我们这种呃所谓的算法的话呢,是最简单直接的,那相应的话呢,它这个性能也是最差的。能理解了,没问题是吧?好,那么通过这个的话呢,我们能不能得到一个非常浅薄的一个结论呢?实际上也可以,那就是我们刚才也提到了,说这个A和B呢,它做连接的时候呢,没有任何索引,是不是小表驱动大表,那么大家你看我们从这个读取记录数数上来看啊,还有这个从我们这个内表扫描次数上来看,这个里边呢,很显然你要看这个的话呢,它俩的权重是一样的,这个好像没有说谁的谁作为驱动表更合适是吧?但你从这儿来看的话呢,是不是影响因子比较大的就是我们A呀。
09:19
啊,那我们的A的话呢,是不是越小越好。那就A跟B相比来讲,A越小越好,那所以呢,我们要选择的是不是小表来驱动大表。对吧,哎,小表的氢大表就这里边A呢,要小一点会好一些,好这个呢,就我们说的这个点,那么接下来的话呢,我们说一下这个叫inex nlg index呢,自然而然就是索引的意思,那我们引入这种算法的目的呢,就是为了减少内层表数据的一个匹配次数,大家你看到我们在这个simple这种场景下的话呢,A每来一条数据呢,这里边儿呢,全表变了一遍,这个成本是很高的。是吧,那怎么办啊,那这时候我们说呢,给哎这个相应的,咱们就以这个B表为例吧。咱就咱其实相当于是目的让他想当这个被驱动表啊,所以呢,我这时候就给这个B字段呢,去加了这个索引了,那么加上索引以后,那这个事儿呢,就简单很多,从A表里边我们来一条记录,来一条记录之后的话呢,我们直接跟B表中的这个字段去做关联的时候,因为你有索引啊,是直接我们就从这个索引里边呢去找了啊找这个B加数是吧,很快的话呢,我们可能就定位到这条记录,而不是呢,像原来一样的,是不是一条条去做便利了。
10:23
啊很好啊,这个呢,性能呢,显然呢是得到了提升啊,主要是通过这样的一个方式,那么如果说我们这个B字段上呢,它是一个这个非主键索引,或者叫非居组索引,二级索引啊都可以啊,辅助索引一个概念,那我们要是最后呢,Select的相应的信息,你可能还需要做一个回表操作,那如果说我们这个B座呢,恰好是这个主键的话呢,那就不用回表了,那就性能会更高一些,OK,那么在这种情况下呢,我们看一看这个开销。啊,这呢做个对比,所以我把这两呢都列出来了,首先我们这个外表扫描次数呢,还是一内表的扫描次数的话呢,你看我这写的是一个零了啊,不用我们再去扫描这个全表了,而是我们直接呢找这个索引这个B加数对吧?所以这是零,然后读取的记录数呢,那我们A这里边呢,你不是一个一个要都读一遍,这呢首先是A对吧A个,然后B这块的话呢,那你到底读了多少个呀,那就看你到底匹配了多少个了,所以呢,加上B啊match匹配的这个数据。
11:19
那接着我们这个照的次数呢,照这个次数的话呢,我们就要A乘以index,这个叫he,这个he,因为我们这个B加数里边呢,咱们看你有几层了,比如我们要有三层的话呢,哎,是不是相当于我们这个A乘以就是来一个,我们这呢,是不是有三层来一个有三层是不是就A乘以这个代这个高度,这就可以了。哎,没问题,然后我们这个回表的记录数呢,回表的话呢,如果我们要是主键索引的话呢,就用不着回表了,你要不是主键索引是这个二级索引的话呢,那我们这种需要做回表,那就看你到底匹配了几条数据了,所以说呢,这是有可能出现的这样的一个场景。没问题,那这呢,很显然是我们是不是追求的一个方向啊好,但是呢,往往事实呢,事与愿违,什么情况呢,有的时候呢,我们没有加索引,这个呢,就属于有的人这个经验比较少是吧,不懂,所以呢他就没有加索引了,那显然呢,是不是就蹦到我们这叫simple了,这是一个情况,那么第二种情况呢,就是我们加了索引呢,但是你的circle的一些错误的写法,导致我们这个索引失效了,那么失效的话呢,是不是又推成它了,那它呢是很崩溃的,那怎么办呢?这时候我们说这MYS呢,又设计了一个比较好的一个算法,叫做block啊NLT。
12:23
Block就是块的意思。不是阻塞了啊,这叫块啊,这个它是什么场景呢?引入的目的是什么呢?哎,大家呢,你首先针对于咱们说的这个simple啊,咱们再磨叽两句,哎,Simple是个什么场景呢?这个来回往下切哈,哎,咱们还来这看我呢,这个从A表当中取一条数据过来,取完以后的话呢,我们这个B表中数据啊,我需要呢,把它加载到内存当中加载过来,然后呢,让我们这一条数据呢,诶走走走走走走一遍。走一遍之后的话呢,你注意我们加载的这个操作完以后,加载这个B,把这个数据啊,它就给清掉了。
13:00
清掉以后的话,你再取第二条数据过来,我们再加载一遍,然后呢,你再啊比比比比一遍,然后呢,这时候结束之后呢,这块又清掉了,以此类推,显然的话呢,这个IO的次数是很高的。啊,那这时候我们希望什么呀?减少我们这个非驱动表它加载到内存中这个次数,那怎么能减少次数呢?那这时候呢,我们这个次数呢,是不是直接关联的就是我们这个A表中的这个条目数啊。那A表中条目数,这个条目数少一点会好一些,但是呢,条目数呢,这不是我们能控制的,你相应的色口语句,你就希望查完以后呢,这个对应的数据就是100条,那也没办法对吧,那怎么办啊,那我们这时候就要控制你加载到内存中这个A的条目数的一个多少,我们刚才那是不是一条条加的,现在呢,要以一块一块的去加,比如说我们一共是100条,咱们一次性的来这个60条。是吧,哎,或者我们再极端一点,一次性的把这100条呢,全加载过来,全加载过来的话呢,那我们这时候呢,这个这100条数据就完全的给缓存起来了,然后呢,把我们这个被驱动表B拿到内存当中,那这时候呢,我们就一次性的啊,全做了一个比较了,那你就不用呢,再去把它销毁掉以后呢,再去加载,因为我们一次性加载过来了。
14:11
但是如果说呢,你要这时候呢,我们往内存中加载了是60条,还剩呃,咱们假设一共是100的话,是不是还剩40啊,那就相当于我们是不是分了两次啊,那就意味着我们这个被驱用表呢,是不是要加载两次就可以了。哎,加载两次就可以了,那你要是这个呃,来的40呢,那这时候是不是就40,四十二十,那就得三次,那有同学说那肯定是希望一次最好,对吧,那这时候呢,一次能不能达到呢?那就看我们这个缓冲缓冲池的这个大小了。那这个受影响的呢,就是我们下边提到这个,哎,Buffer啊,这个block,这个buffer的一个大小了,行,那这块呢,就是我们提到这个叫block这样一个场景。哎,照应buff是吧,哎,它的一个大小啊。好,那么这时候呢,我们就已经把这个事儿呢,其实是说清楚了啊,我们再稍微的看一下这个图,我们呢,把这个驱动表当中这个数据呢,把它呢,诶放到我们这个照影B火当中,那如果说呢,我们一次性全都能放过来,那太好了,那这时候我们这个被驱动表呢,只需要呢加载一次就行,然后他呢,就一次性的跟我们这个去做对比。
15:13
那你要说一次加载不完怎么办呢?你又分多次,那加载了几次,假设呢,我们加载了K次,是不是就K乘以啊,这直接就K就行了,我们这个呢,是不是就直接呢,往内存中加载K4就OK了。啊,这是我们说这个点啊,那这呢,我写了一个注意呢,其实是关于我们这个正B法里边到底都放什么了啊,除了呢放我们这个A之外,你看我这里边是把A放在这了,还会放什么呢?还会放我们这个select当中,比如你这个驱动表是A,你查询的A的那个字段,比如我查A的俩字段,然后那俩字段的话呢,还不是A这个字段是吧,那也要放在我们这个转B当中。那这样的话呢,其实你就我们说呢,尽量呢,你要没有用的字段是不是就不要多去写了呀,啊同学来个十来个星,那很崩溃了,这是不是占用我们这个照buff了是吧,导致呢,你这时候呢,一次性放在这个条目数是不是就变少了呀?OK,那再一个的话呢,就是如果我们有N个join的话呢,相当于N个表呢,做这个join的连接,这时我们就会有N减一个的这个join b。
16:07
啊,这个都很好理解,OK。那么在这种场景下,我们看一看它的一个成本的一个消耗情况,首先呢,外表扫描呢,还是一次,对吧,扫描一次就可以了,然后内表扫描这个次数是多少呢?诶大家你看这是我就有变化了,我们这个A呢,乘以use的column size,其实这块整个得到就是我们这个A表,它的一个相当于内存大小了,那就是你要使用的这个字段的内存大小,包括呢,就是我们这个A字段本身,还有呢,你这个select当中涉及到的A表中的这个字段都算上,然后除以呢,我们这个召唤B一个size相当于呢,我们一共要分成几次。啊,比如说像我刚才说的,它有100条记录,我们40,四十二十,这个相当于我们就分了三次呗,对吧,然后再加上一一呢,就是我们本身这个,呃,内表扫描的一个次数啊,针对于我们这个呢,是不是也得扫描的这一次啊。然后读取的这个记录数啊,读取记录数呢,A我们不是要都读一遍嘛,这就是这个A了,然后后边这块呢,就是我们对应的这个次数,你再乘以一次的话呢,这不就是B个嘛,然后B乘以我们这个次数就可以了。
17:07
然后这个照的这个次数呢,就是B乘以A啊,还是B乘以A这呢就是零,那显然的话呢,我们这个block这个NLG是不是就比我们这个simple这种情况要好很多了呀。OK啊好很多,那么这时候我们肯定希望呢,说这个,呃A呢,这个你次数呢,加载到专buffer的次数越少越好,那这时候受影响的参数是什么呢?哎,这里有两个,首先第一个我们呢要决定了你是不是去使用这个block啊,Next这个look。啊,你是不是使用它了,那这时候我们可以通过这样的一个参数呢,去做一个查看啊把它呢,诶CTRLCL一下,嗯,这个我们查看的话呢。呃,咱在这块看一下也行啊,在这块看一下也行,有可能这个查看出来这个比较长啊,可能效果不一定好啊。哎,分号一下。哎,选中我们走一下啊,这个有点差是吧?哎这么着也行啊,大家你可以复制一下。嗯,复制到复制单元格。
18:02
啊,这个放在这个面上。哎,这个我用它好像不好啊,还不换行了。找一个world。嗯,张过来,好,这里边呢,我们去找一下啊,刚才我们提到这样的一个参数就是blocked,这个是啊,诶在这呢是吧,哎,眼神还不错啊,Blocked啊na loop就相当于呢,我们相当于是把这个block的这样的一个LL阶段,是不是有个启动的一个状态,OK,没有问题啊。那么它在启动这个情况下呢,我们就可以使用这样的一种算法了,那这时候我们主要受影响的就是这个障碍buff的一个size了,没问题吧,好,那么这个障碍buff size有多大呢?咱们说默认情况下呢,它是这个256K啊,这个我还是在这块呢,直接粘过来。啊,选中。哎,走一下,哎这呢你一看啊,就是256KOK,哎,我们可以呢,去设置这个参数,这个大小,你把它调的大一点啊,这个我就不去演示设置了,这就set就完了,对吧?那这时候我们想说明的是呢,在32位系统当中呢,最多呢是有四个G啊,在64位这个系统下呢,可以申请大于四个G,但是比较特别的就在Windows下呢,当你在64位的情况下呢,它呃相当于有一个上限,还是这个四个G啊,这个多的部分就给截断了啊这是我们说的这样的情况,好那么这样的话呢,咱们就相当于是通过这个底层的一个介绍啊,梳理一个支撑给大家呢,去讲解了一下,为什么是得到我们上一节讲的这样的一些结论,那整体呢,从这个效率上来讲的话呢,我们说这index方式呢,肯定要小于用blocked blocked是不是小于这个,哎,呃,Index这也要好于我们这个blocked要好于我们这个simple的,这个是没问题的是吧?诶,OK,那么基于这样的场景的话呢,我们再把上一节提到一些结论呢,我们再去强化一下。
19:46
我们提到了一个概念呢,叫做小表来驱动大表,严格上来讲这句话呢是不对的,或者呢是不精确的,怎么叫小表,怎么叫大表呢?我们其实严格上来说应该叫小的结果集来驱动大的结果集,这句话呢是更精确,为什么这么讲这个,哎我我这样来说啊,我们这个表假设呢,A表是吧,它呢有100行数据,我们这儿呢,是这个B表,它呢有1000行数据。
20:12
对吧,1000万数据好,那么这两个表呢做关联,那我问谁是小表,谁是大表,大家可能呢会异口同声说说A呢是小表,B呢是大表。好,那我呃假设呢,你目前说的是对的啊,我现在再明确一个条件,就是我这儿呢,在两个表连接之后呢,我加了一个外耳条件,这个外耳条件当中啊,我给这个B啊做了一个限制它的某一个字段呢,比如说小于这个某个数,导致我们过滤完以后的话呢,我们这个B表啊,我只查询到其中的50行数据。那我会让数据,然后跟这个A呢,去做这样的一个关联,那我问那这时候呢,谁是谁小谁大。啊,有同学可能就迷糊了,说我们到底呢,是呃看这个B的这个1000行这个数据呢,还是我们看这个B中的50行这个数据呢?啊,那这里呢,我告诉大家,就是我们要看的过滤以后的这个数据。所以说呢,我们不应该说呢,哪个表大哪个表小,而是呢叫结果集对吧,那我们这过滤完以后啊,那个结果集呢要小,所以呢,它其实更偏向于是一个小的,它呢就偏向于是一个大的了,这呢是我们从这个什么呀叫表的行数角度上来看的,那光看行数行不行呢?也不行,真正意义上我们说谁小谁大啊,我们应该是表的行数再乘以每行的一个大小。
21:21
哎,这又是什么意思呀啊,这个呢,主要影响的就是我们往这个block,这个我们这个buffer当中啊,照样buffer中我们去放的时候呢,是不是你这个每一条数据呢,越小就越好一些,实际上呢,是这个意思对吧,那每一条这个越小越好,其实就是我们每一行的这个大小了,来我给大家呢又写这个例子,大家看。啊,同学一看到这两个表感觉有点懵啊,眼有点花,说猛一看都一样,其实是有区别啊,我我也不用给大家时间呢,去暂停去剖析了,我直接跟你说啊,你看我这呢是from,哎,这个T1呢,去啊,连接我们这个T2,这呢是T2连接第一,这是有区别的,也就是说我们这个strict John什么意思啊,就是我们这块呢,明确加上了一个strict join的话呢,就是不要查询液化器去破坏我前后的顺序。
22:04
也就是说呢,我这样写法的话,就是让T一来充当驱动表,T2呢来充当被驱动表的啊这个呢,反过来对吧?哎,就是不要让它破坏我。帮我去优化了啊,就是就是用我现有的这样的一个,前面是驱动表好,那么这两个的话呢,相当于是驱动表和被驱表是不一样的,对吧,那么后边这个条件呢,其实都是一样的。那么在后边的都一样的情况下,哎,其实相当于我固定了这个表的行数了啊,这个表的行数了,然后接下来的话呢,我们看到底谁算小结果集,谁算大结果集啊,主要区别点呢,就在于我们查询这块,你会发现呢,我们这个T1呢,我只查询了B,而T2的话呢,我们查询了它所有的字段,咱们假设呢,T2的一个字段呢,不止一个啊,很多个字段,那这时候呢,我们把谁这个呃作为驱动表,让他呢,去用我们这个状语B法更合适一些啊。啊。这个我结论已经写到这是不是推荐我们写这个呀,为什么呢?啊,因为我们加载的时候,如果把它当成是这个驱动表,我们相应的往这个叫buff分钟呢去存放的时候啊,那我们这时候呢,是不是只放这个T1的B这个字段啊,你这个关联条件的话呢,还是B,那挺好,就只放这个字段就行,那同样的这在相同的这个八分大小的情况下呢,我是不是放的这个条目数就会更多一些啊。
23:16
OK,那你要是用这个T2呢,作为这驱动表呢,T2这个驱动表它涉及到字段很多,那你是不是一行数据呢,这个占的大小就多,导致我们放这个条目数呢,就会变少啊,哎,自然而然的一个道理,行,所以呢,我们就推荐这个点啊,所以当大家把这个结论呢,记住。啊,小表驱动大表,主要本质上来讲呢,就是减少我们外层循环的一个数据的一个数量。那接着的话呢,我们说为被驱动表匹配的这个条件呢,我们去增加索引,就咱们上面这个结论是在两个表呢,比如都没有这个索引的这个情况下来谈的啊,这个字段没有索引,然后呢,接下来你可以考虑呢,给我们这个被称表呢,这个相匹配的这个字段呢,是不是去加这个索引,这样的话呢,我们相当于是达到这个index这样的一种场景,是不是减好减少这个内存循环这个次数了,对吧?然后在这个情况下呢,我们还可以再去加大咱们这个照唤buff的一个size。
24:03
那这个时候呢,是不是使得我们一次缓存这个数据呢,就会越多一些,哎,导致我们这个数据的话呢,是不是就会越小一些啊,它越小的话呢,是不是整个我们这个数据呢,它就会,哎这个值得到的这个成本呢,是不是就越低一些啊OK。好,这呢是我们说这一点,然后呢,下边要减少驱动表不必要的字段这个查询啊,那你要不必要字段就不要查了,实际上呢,就使得我们这时候呢,在放这块的时候呢,是不是你放的每一行的空间就占用的就少一些了,那放的条目数呢,不就会多一些了,哎,OK的,没问题是吧?好,那这个呢,就比较清楚说清楚了,呃,正常来讲的话呢,我们说到这儿呢,就算是完事了,但是这块呢,诶注意,因为咱们讲的是8.0的这个麦斯版本,这块呢,就涉及到这个新特性叫哈希John。那有同学呢,其实呢,就早已经发现我们这里边呢有一些问题了,什么问题啊,你看啊,我刚才在这个做测试的时候,有同学呢,就会发现说老师这块呢,咱们也没有看到,诶这个我们再往下拽一下啊,说我这也没有看到,说咱们使用的这个呃,相关的这个叫呃,Block的这样一个转的方式啊,比如我们这么着一下吧。
25:07
啊,在这是吧,你看叫using John buffer,哎,你看说我这块呢,也不是用的这个block呀,老师你看这块呢,叫哈希John,这又是什么鬼,哎,这个是因为我现在用的是八点零点,咱们装的是8.0.2526这样的一个版本导致的,对吧?哎,大姐你看啊,现在的话呢,我这么着,咱把这个事儿。到这吧,CTRLCL一下,我在这160,那其实对应的就是我们max5.7吧,好我把这个呢,重新的再去创建一下走齐。再把这个数据呢,咱们添加一下。好,然后呢,我们再去做这样的一个测试啊,大家都去看一下。大家看这个时候的话,你会发现在5.7当中,咱们呈现的是不是就是咱们刚才说的这个block是吧,NLG呗,但是在这个8.0当中呢,它不是的,它叫这个哈希John,诶所以这块呢,其实如果呢,我们谈到上边这块,包括大家在面试当中,你谈到了我们这块呢,啊,也就打一个八十来分吧,是吧,诶80多分还不错了啊,至少呢,都懂啊,说的还算清晰透彻啊,小杰这个呢,也能表达清楚啊,已经不错了。
26:09
哎,但是你要想能达到优秀啊,达到90分以上,95以上,95分以上啊,那怎么办呢?要引入我们这样的一个新特性,叫哈西转。我们从MYSQL8.0.20开始就废弃了这个block的这样方式,我们引入了叫哈希传,而且呢,在8.0.18这个版本之后呢,呃,这个这个就明确的就都开始使用这叫哈希照了,那么哈希照应跟我们上面这个ne的这个loop这种方式的呃,区别在哪呢?呃,对于我们这个数据集比较小的情况下,我们这个呢,还可以啊,还可以,但是一旦我们这个数据集比较大的时候呢,我们其实推荐的就是这个哈希转的方式。那么在这个液化器使用的时候呢,它把两个表中较小的这个呢表利用这个照K在内存中呢去建立这个散列表。然后呢,这个扫描较大这个表啊,并探测这个散列表,找出与这个哈希表匹配的这个行,哎,这样的一个原理,具体细节的话呢,我其实就不想在这儿多去描述了,那么在咱们这个呃,高级部分呢,咱们也会相应的去编写这个对应的一些教材啊,哎,补一些教材了,就是一本教材,然后呢,在这个教材当中,关于这个哈希John这样的方式呢,会进行一个深入的一个讲解,咱们这个视频呢,因为整体的时间已经比较长了,所以不就在这就不在这儿呢,展开来说明了。
27:23
OK,那么二者呢,做个对比,还一兆呢,它这个特点呢,就是只能做这个等值点击啊,这个咱们都比较清楚啊,如果呢,你呃表的数据比较少呢,就在内存中,如果呢,这个数据比较多的话呢,因为它针对这个数据量比较大的场景呢,也是适用的,所以它可能会占用这个临时空间啊,我们使用不同的区域临时段啊这样的一些场景。OK啊,下边呢,简单是一个描述,哎,大家呢,知道我们这里边呢,其实8.0.20以后,我们主要用的这个叫哈希照啊这样的一个方式就OK了。好,那么关于这个照那底层原理呢,咱们就介绍到这儿。
我来说两句