00:00
接下来我们来看一下这个所谓的CPU基于代价的优化CPU优化器,那咱们再结合前面的场景,应该在哪一块,就是它。物理执行计划其实生成之后,会基于CPU帮我们选择一个代价相对较小的执行,那最终选择这个代价小的物理执行计划啊,作为最终的物理执行计划,其实我们展示看到给我们的就是已经是他了啊,已经是选择完了,那我们怎么来衡量这个代价呢?对吧,就像咱们举那个例子,你要达成一个目的啊,比如说你要报复一个人,你的方式有很多种,对吧,你可以现场骂他,你可以打他啊,你可以拿刀刀他,对吧。但是你衡量的依据,比如说骂一下你不会怎么样,你打一下你会怎么样,你是不是还得衡量一下你个人实力,对吧,你骂得过他吗?你打得过他吗?对吧,怎么样的这回事儿,那到底是在这里,他是以什么为依据呢?所以他要求咱们第一个要先做一些信息的收集啊。
01:16
表也好,列也好,相关的统计信息要提前收集好,他才能去以此为依据做一个判断,哪一个代价更小一点啊,那CPU的优化呢,咱们了解一下基本概念啊,它主要在一个物理计划层面。原理是计算所有可能的物理计划的代价。第一个先计算所有可能的代价,并且呢挑选出代价最小的物理执行计划。那怎么来挑选呢?它充分的考虑几个,第一个是数据本身的特点,也就数据的大小,数据的分布,还有呢,咱们操作算子的特点。代价。颜值就分为这两大类,一个是执行节点的代价,一个是。
02:04
操作算子的代价就是这两个玩意儿啊。那么像数据局的这个代价,咱们可能不好去控制,但是操作算子这个代价咱们是更好去控制,对吧,所以咱们主要是研究这个啊,操作算子的代价,那在操作算子里面最。代价比较大的往往是一个join啊,所以咱们在谈到CPU去做一些优化调整的时候,往往呢,更关注的是一个的一个优化。那比如说他能帮我们实现一个。Doing的顺序调整,还有一个doing类型的转换等等,一会呢,咱们用实际的案例来感受一下好了,那现在第一步我们说了要收集相关的信息才能来执行这么一个CPU,那这个收集呢,需要咱们执行特定的语句。
03:08
那就是这么一个语句,首先生成表级别的统计信息,一个主要统计两个东西,第一个呢,就是这张表一共有多少行。第二个,这张表的大小就多少G多少兆这样的。都它是以字节数来衡量的字节,那这个是行数啊。主要就是生成这两个,那这个呢,需要咱们用下面这个命令,你看分析表啊,这个是表明,然后计算它的统计信息啊,把这写成表明吧,不然有些人看了可能会误解啊。那我们可以先来看一下hi的原数据库啊,因为是表嘛,原数据库看起来更直白一点,嗯,那我这个是my circle,连接上my circle,我have的原数据库是放在那个my circle里面,是在这里,那首先我们看一个TBL看一下表吧。
04:09
TS,咱们想要的是最原始的三张表啊,在哪呢?Cosy,还有一个sciencefor,好。还有啊,就这三张嘛。这三张表我主要是想记住他这个ID名,要不然一会看参数看不懂啊。把它放这,接下来看一下表参数,这个元数据表。呃,应该是在这里table PAR,首先咱们瞅瞅这个162的啊,你看这里只有ID对吧,162诶刚好在这。这里是不是全是162的对吧?162对应的是咱们这张cos pay表,那163对应的是s costs对吧?164对应的是。
05:04
Co shopping car这张表,反正我们就知道162 163164啊,简单瞅一瞅他们的属性,你现在当然瞅不出啥了,对吧?我们先截个图。好,这个先放一边,那接下来咱们要来执行这个表信息的统计,对吧?好,这个先放着,那除了表级的信息统计啊,咱们还需要有一个列级的信息统计,列级的信息统计这个语法有点相似啊,分析表,然后呢传递一个表明。呃,计算统计信息,然后呢,For cars后面要指定咱们要去统计的一些列啊,我还是把这替换一下,这是表明。这个是列啊,比如说列一列二列三,你要你你要统计几列都行啊,看你的需要。
06:06
那统计完的信息一会儿呢,咱们可以从这个原数据库里面这张表来看,那有的人会觉得很麻烦,对吧,其实它也提供了显示统计信息的语句啊,在哪呢?呃。在下面这里,Dis form。在这呢,是不是会显示打印表的信息啊,这其实跟汉普语法是一样的,那在这里也可以看到啊,一会咱们就可以看到了啊。呃,替换一下表明,那显示列的统计信息也很简单,This format format,然后加表明加列名,它每次只能显示一列的统计信息啊。好,那这个呢,我也不用去提交集群了,那太慢了,对吧,咱们直接看一下这个代码,在咱们CPU文件夹下面有一个sta collect,这是信息统计,我专门写了一个。
07:06
一个类啊,那我们看看。这边我是封装了一个方法啊,传进来一个表明一个列的。集合啊,是一个字符串,那我们看看我会做什么啊。首先呢,用咱们刚才那个DSC语法,把它的统计信息先打印出来啊,这样咱们就不用去原数据库看了嘛,对吧?呃,然后呢,执行这个所谓的统计命令,呃,然后。把统计后的结果。展现出来,最后呢,再查看一下咱们这个统计的信息变成啥样,咱们拿它跟它做一个对比,好这里呢,表级别的信息就有了,再下面。我又封装了一下,咱们把传入这个列的符串,把它按逗号分隔一下,然后呢,对它进行一个遍历,然后挨个对每一列都做一个查看,查看完之后呢,咱们就一样的执行一个什么呢。
08:10
分析表计算信息对吧?For currentrs啊,把这个列都给统计一下,统计完之后咱们同样的还是再去遍历这个列,每一列的信息,再去做一个对比打印出来啊,这就是咱们这个类做的事儿啊,也没必要去集群了,咱们直接执行啊。对比一下。哦,那个logo星要打开对吧,ID之星好。好了,现在执行完了,我们拉到最上面挨个看一下来,首先是CS cos这张表的一些信息,我把它打印在控制台了,其实这些信息呢。跟原数据库里一样嘛,Cosplay是这个嘛,对吧,162,那咱们看看162的属性。
09:09
啊,不仅仅是这个啊,不仅仅是这个,它这里打印出了一些列的列名跟那个类型,还有它的出示。好,后面是一个分区的信息,后面这个呢。是详细的表信息对吧,属于哪个库的表明叫什么,所有者是谁啊,创建时间等等等等。这个东西咱们最关注是这啊,先把它拿着。再往下我们这里是开始执行统计那个命令了,对吧?Analysis,那么在执行完之后,我们又查看了这个变化,前面这些字段不会变啊。最关键的是在这里啊,来对比一下前后啊。
10:01
这里多了一个东西,叫他。你在右边是找不到的啊,右边没有。右边没有这个玩意儿,这个就是咱们执行那个信息统计采集到的一些信息,那这里展示不全对吧?嗯,你也可以调整这个受的打印,把它不截断,那我们直接从原数据库来看吧。来,我刷新一下。刷新好短们呢,先来关注162 162啊,从这开始。162来对比一下啊。这一块你粗略的看起来是没有什么变化的。但是他会多很多东西。咱们直接拉到162最后几个属性啊。他多了这两个。哎,啊,框错了,是这样的。你看162最后面有这个吗?没有吧,它最后一个属性就last什么time对吧。
11:06
就没有了。那我们看这里一个是什么?关键词是statics对吧?统计信息,然后呢,Number Rose有多少行对吧?这边统计出来咱们这张表有2000万行,这没毛病啊,那总的大小大概多大呢?是这么多个字节啊,这是可以啊,这是bit。这个就是咱们收集到的表的统计信息,那我们再接着往后看啊,除了表,咱们是不是还统计了列啊。咱们把其他表都看完吧,那163我们再瞅一瞅,它应该也多了很多东西,我们先关注这个163是不是多了两行统计信息,一个是行数,一个总大小,这个的行数呢,就是。咱们那个小表嘛,163就是这个C啊1万行,那它的大小是这么多个字节,再看164往下拉。
12:04
他是不是同样也有这两个。行数大小啊,这个是3000万行差不多啊,这个就是那个接近五个G的那张表。那这个是字节数啊。那为什么这个大小好像跟咱们那个五个G4,应该是4.7还是4.8吧,对吧,不太一样了,这明显是二开头的,你忘了咱们存储的是什么PU对吧。它是按这个来文件的大小来计算的,它可不是按原始大小,咱们用的是pack啊,而且是八口默认帮我们加了一个snap压缩啊,如果你们忘了的话,咱们呃,那就来看一下HDFS。比如说这这张表随便找一张。点进分区大家可以看到,首先存储是怕另外做了snap啊。这张表,所以呢,他统计出来这个大小是对的啊,刚才那个地方这是对的,这个是表级别的统计,那这边就挨挨个呢去打印了,那我们接下来看一下列级别啊,列级别列呢,咱们把这几个先去了嘛。
13:19
诶,销毁啊,好,还是这张表对列进行一个统计,那这是最原始的三个列,对吧,ID dt dn。那这是第一个,这是ID那个字段,它会统计些什么呢?首先列明叫ID类型,还有呢,注释在接下来这几个,这个列的最小值,这个列的最大值,这个列的闹值。对吧,这个列去重后有多少个平均的长度,最大的长度还有一个直方图。一些信息原始都是没有的,因为它必须咱们去收集它才可能有啊,那同样这是第二个列DT,这第三个列DN啊,最开始这些全都是闹,那我们再往下看,这是执行的一个列信息收集,收集完之后咱们再接下来看,你看现在是不是有了。
14:16
这个列名是cos ID类型big int,注释还是没有,你看最小值是零,最大值是9999 now值的数量没有。那去重之后的数量9000多,9571对吧,平均长度八个。长度是它那个,比如说就字符串的长度嘛,啊,平均是八个,那最大长度也是八个。因为这个咱们固定给了一个八个字符串啊啊就就就八个啊,是八个直方图没统计啊。那同样的DT这个字段,这些也都有吧。能统计的都统计上了啊,那这些对咱有什么帮助啊,像这个最大最小值,这些值就可以在咱们进行过滤判断查找的时候,直接用这个来做依据判断就行了,咱们就没有必要说一行一行去扫对不对。
15:15
那在后面呢,就是另外两张表的信息了,同样的啊,也是像刚才一样,咱们就不再去看了啊,不浪费时间,那其实列的收集信息在刚才这张原数据表也能体现,比如说1611,随便看一张吧,164。你看它其实是多了这么多东西了,呃,今天是status的这些都是啊,那后面这个单词是不是都Co开头的表示列的信息啊,这就是采集到的,你像这边什么平均长度啊,去重后的个数啊,最大最大最小闹值啊,这些就是统计信息了。所以他们执行完统计之后,并不是说就没了,而是会持久化到原数据库。
16:01
所以呢,这三张表现在已经拥有了咱们的统计信息,那在接下来统计完之后就是咱们来使用CBO了,那使用CBO呢,需要咱们明确的把它开启,要不然它不起作用啊,它是一个Spark,搜狗CP.na默认的是一个false。我们要把它打开,那除了打开之外,它还有很多的其他可选功能,第一个我这边列了一个常用的啊。Join reader等enable,这个是使用CPU自动调整连续的inner join的顺序。什么意思呢?举个例子,咱们如果有个circle是这样啊,A join b。然后得到一个,呃,比如说得到C,然后C又要再跟D做一个交,得到。EE跟F再交引,要得到一个G,那咱们在这个circle口执行的时候,是不是得先执行它得到C之后才能再跟D去交易呢?对吧?也就是说后面的每一个都得等待前面交完才能去执行,那么如果开启的CVO啊,经过他的判断,有可能把我们调整成这样,比如说他先A跟B。
17:18
Join得到,呃,C,那他可能判断出来我那个。D跟F先做一个交易对吧,然后C呢。再跟他们一起join,再得到G,也就是说这个跟这个是不是可以同时进行对吧,就不用像前面这样一直等了,它会自动帮我们调整,当然目前咱们没有那么多的表来让他调整,而且代价也体现不出来,那咱们这边就来感受一下什么呢,比如说。呃,优化标准的类型,对吧,来试试。那这边我也准备好了一个类啊,一个cb ten,那在这呢,咱们会。
18:06
把这两个参数打开啊。哦对,还有一个参数忘了介绍啊,还有一个参数是这个啊,一般这两个是成对出现的。下面这个是。你想要调整自动的inner顺序的话。需要有一定一个阈值。那这个值目呢是12表示呢,如果你是12张表以下的join啊,它可以自动帮你调整,超过12张表它就不调整了啊,因为它要调整的话,还是得判断蛮多的啊,当然你可以调整这个数啊,可以调整这个数,那一般也没必要的。没有这个必要。啊,那这边其实我就简单简简单单开个c po就行了,那我们看一下这个案例的语句,语句啊,第一个呢是一个。这个。
19:00
这个是一个两张表的内连接,对吧,D开耳机嘛啊csc跟CP2张表,那接下来呢,就是做了一个group,再做了一个上,就这个搜狗很简单,勾引完之后分组聚合,那么这个时候我们直接来跑一下,现在呢是没有开启CBO的。啊,那个logo星又忘了打开了啊,打开logo星啊,执行。看到这个结果出来了,那我们看一下UI页面啊。啊哦,本地执行的话要直接local host4040。咱们直接点一下这个circle啊,咱们也是看执行计划,只不过呢,咱们在这页面看更直观一点啊,省得那个打印的文字大家看老半天啊,看老半天来我们看这个执行计划啊,大概再来回顾一下,这是不是分别扫描两张表啊,扫描完之后呢。
20:09
做了一个过滤对吧。过滤完之后,你是不是要沙包?对吧。Shuffle,那他们在用的沙uffle是由于它是涉及到salt对吧,Salt沙uffle,那这一块他们要各自先进行一个sortt排序啊,那完事之后呢,进行一个交易。之后呢,输出输出完之后,咱们是不是做了一个聚合呀,Group by嘛,还做了一个萨那,我们说了flink,呃,不Spark circle,它自己帮我们做了一个预聚盒,像这种场景是允许的,所以他在下一次的杀火之前。也就group by这个沙uffle之前,他先进行一个本地聚合,聚合完进行杀uffle shuffle完。
21:00
又一次全局聚合对吧,这个过程咱们前面讲的知识点也有体现了啊,就整个过程,那咱们现在关注的是什么呢?这个地方。现在是梦蚯蚓。啊,慢交易好,我把程序停掉。停掉之后我打开CPU。打开一个CPU重新执行,那我们再看看它的一个改变和效果。好了,那现在呢,这里已经出结果了,我们去页面看一下啊,重新刷新一下这个页面。点开这个circle,还是点第一个来。这里。已经有变化了,来,这是读一张表,这是读另一张表,两者同时进行的吧,对吧,然后这个过滤啥也不讲了。那这边。
22:02
变成了一个什么?哈希,对啊不广播对不对,广播交换,然后进行了一个广播交引啊,这个其实就大小表join引啊,大小表交。他觉得这样更有代价啊,更好。更快啊。那后面的都是一样的,你看这是一个本地聚合这块对应的就是啊,再啰嗦一遍吧,咕BY某某某,然后做了一个上什么的,像这种它不是杀uffle完之后再去聚合的,它是先每一个map里边先聚合的,能聚合的先预聚合,聚合完才进行杀否,杀否完到了对应分区再次进行汇总。啊,这样是不是效率高啊,其实从这能体现啊,好,那我们来回过头说这个事儿了,这个东西,呃,一会儿后面的内容咱们也会介绍到,我提前讲一下啊,因为要体现出这个CBO的价值,呃,这个广播join就类似于hi里边的一个概念,叫map join。
23:11
就是大小就印的时候啊,咱们要来用,那比如说呢,咱们它默认的小阈值是十兆。默认的阈值是十兆啊,大家注意,默认阈值是十兆,那么大蚯蚓小。他会这么来做。他会将小表。广播以广播的方式广播到大表的map端。也就是说这个时候不用去做一个shuffle的,大家也可以发现咱们join的时候其实是没有沙uffle的,对吧?是group才有的沙uffle,也就是说在map端就完成了一个聚合,那把小表广播到大表的map端。的内存里面,这个时候大表就在map端与小表进行了一个join,这个就是咱们的一个广播join。
24:07
啊,类似于hi普的map交易啊map交易,那为什么咱们前面这个我也没指定其他参数,它为什么就是有这种有沙的交易呢。那是因为CBO基于统计的信息。统计的信息它能识别到,其实咱们是要做一个有一个过滤,过滤完它是以过滤完的结果为判断依据,要不要广播就业,那如果是传统的,它是以原始大小做一个判断啊,原始大小。这就是区别,但是由于有了统计信息,咱们才他才知道其实用这么多就行了,那他发现用这么多我用广播交就行了,这就是他的一个代价选择过程。嗯。
25:05
对比一下这个circle啊,把刚才那个代价选择我再强调一遍,其实咱们这里是不是做了一个过滤啊,就是把这个一个订单ID写死了,我就要这个ID,其他都不要啊,对吧?那你想想我过滤出来这个数据集是不是应该特别小啊,就是应该特别小对吧?那既然小,那肯定呃是满足那个广播就业的,就应该走广播就业,那么原来咱们没有开CBO的时候,但他并没有走广播就业,他走的是这个STEM就业。那是因为他判断是否满足小表这个要求的时候,他不会去将数据集过滤,过滤它不会以这个为判断,而是判断什么呢?原始表,也就是说这张表原来多大,这张表原来多大。它是根据原来的表大小去做比较的,那开启了CPU之后,他就知道,哦,我要过滤,那过滤完之后,其实我才剩这么一点,然后再进一步判断发现,哦,我满足广播的条件,那我就走广播条件就好了,这样代价不是更小吗?对吧,那你想想。
26:10
这个是不是特别好啊。对吧,帮我们省了很多事儿,所以咱们也是建议你平时的时候,嗯,像这种你就可以开启CP了。那如果你有多张表进行join的时候发现效率很慢,你也可以把这个调整join顺序的参数打开,对吧?那大家知道默认是12个以下调整,如果你需要阈值大一点,你就调大一点,这个就是CPU的实际使用场景啊,一定要记得提前要先做一个信息的统计才可以啊,好了,这个就是CP啊,很直观,咱们直接就看到了一个区别。
我来说两句