00:00
好,那么这一章的话呢,咱们关于这个索引优化和这个查询优化啊,其实咱们谈的已经不少了啊,大家呢,也看到我们这一章呢,这个字数呢会比较多一些啊,我们讲起来呢,这个东西呢比较多啊,经验性的东西呢也比较多,大家呢需要去消化吸收一下,那么我们在这一节呢,也算是到这个最后了,咱们再谈一些比较散的一些小点啊,这儿呢,因为就不足以呢,把它建成这个二级标题了,哎,把它呢就统一的放在我们这个第12这个小节当中,那我们分别呢来看一看,首先呢,第一个说关于这个ex exist词和这个in的一个区分。那大家呢,在写这个circle的时候呢,经常会发现呢,我们既可以呢选择用in,也可以呢选择用这个exists是吧?但到底这两个我们该选择哪一个会更好呢?诶从这个性能优化上呢来讲,对吧?诶那这时候呢,我们该怎么去看呢?诶说呀,主要呢,我们选哪个还是要看一看这个表的一个大小,主要的一个理解的标准呢,我们可以理解成呢,叫小表呢去驱动大表,在这种情况下呢,我们看看谁的效率呢会更高一些啊这呢给大家举一个例子啊,比如说我们是select星from a,然后where呢CC in select from b,这呢是使用的这个in。
01:05
啊,你比如说我们这呢,是属于这个叫员工表,这个呢属于这个叫部门表,从部门表当中,我们把这个呢,诶这个相当于manager ID啊,或者你叫部门的一个管理者找到,然后呢,看看这个员工表当中呢,你看都谁这个这个这个是我们这个管理者对吧?来把这个员工的信息呢,给它列出来,就这样个需求,然后呢,如果我们把它呢,改写成用这个exists来表示的话呢,那就是这样的一个场景。啊,这个大家一看呢,应该也能看得懂对吧?哎,相当于是一个相关子查询了。啊,相关检查群好的,那么我们这时候呢,该选择呢,是用in呢,还是应该用这个CE呢?诶我们要看一看这个A表和这个B表呢,谁大谁小,说如果呢,我们这时候呢,这个A表比较小,这个B表呢比较大一些啊那你想想我们这个情况的话呢,因为它是一个呃相关的一个场景,它其实就类似于我们所谓的这种叫嵌套循环一样啊,外边是这个A啊,里边呢是这个B,呃像这种场景的话呢,我们建议呢,遵循叫小表驱动大表,那这个A表的话呢,如果它比较小,这个B表呢比较大啊,咱们建议呢,就是使用的这个叫exists。
02:09
好,那么如果如果呢,我们说这个呃,A表呢比较大,这个B表呢又比较小,那这时候呢,大家不妨呢,就使用我们这样的,诶第一种这种场景啊,因为这种场景当中的话呢,你看我们就直接呢,从这个小本里把这个CC呢就取到,然后直接这样这个CC呢,是不是就等于这里边这几个值就可以了。哎,就这种场景呢,它相当于呢,这个性能会更高一些啊,也就是说呢,我们这个呢,是不相关的一个,诶也算是一个子查询了啊,这个呢,属于一个叫相关的一个子查询啊,那这时候的话呢,我们这个不相关子查询,咱们在上面中讲过,他呢就先把这个呢查出来以后呢,给外边用,而我们这种场景呢,是不是先从外边呢,你得送一条数据进去,然后呢,查完之后再出来,再送一条进去,所以呢,我们这时候呢,外边这个表的大小呢,会影响我们整个这个性能,诶它小一点呢会更好一些。好,这是我们说的这样的一个场景啊,这个大家注意一下啊,好,那么接下来的话呢,我们再看一看这个叫count清和我们这个count具体字段的这样的一个效率,诶我不知道呢,大家呢,有没有在面试当中被问到过这样的场景啊,那在很早以前的话呢,这个我了解到呢,面试当中是经常会被问这个包括的话呢,这个在网上当中也有大量的关于这个count新COUNT1,还有这个count具体字段呢,一些探讨啊,这些具体字段呢,又分成了呃,有我们这个主见的这个字段,还有呢,非主见的字段啊等等啊这个讨论的话呢,大家特别的热闹是吧?啊那我们这时候呢,给大家去讲一讲,说到底我们呃查询这个表中有多少条记录性能哪个更高呢?诶,首先呢,大家先注意,我现在呢讲的是MY。
03:43
诶,我讲的呢,也不是呃,所有的数据库当中的一个通用情况啊,因为在Oracle当中还有Oracle它的一些,呃,所谓的存储引擎的一些机制和特征,是吧,我们就不去谈别的数据库了,咱们呢,首先立足到MYSQL上啊,然后的话呢,我们再有个前提就是说,呃,咱们现在查询的就是这个表中有多少条记录,也不是呢,要统计说某一个字段呢的非空的行数,那这个呢就没有意义了,是吧,你找某个字段非空的行数,你用看德清呢,本身可能还都是错误的。
04:11
是吧,这都另当别论,咱们现在要讨论的就是你这个表中呢,有多少条记录确保呢,我们这三个呢,查询出来的结果首先得是一样的,然后呢,我们再去看哪个性能更好。对吧,诶你看我这块说话还是比较严密的好,那么在这种场景下呢,我这儿呢,列了两个环节啊,大家呢,诶其实理解一下啊,我觉得是都可以理解清楚的啊。首先的话呢,我们先说一下这个count星和我们这个COUNT1啊,Count星和这个COUNT1,这哥的话呢,他对所有的结果进行这个count啊这俩的,呃,这俩呢,首先呢,它没有本质上的这个区别,大家可以理解成呢,呃,就是它俩的性能效率是一样的。啊,那既然这样的话呢,很多同学呢,可能就会习惯上去用康乃星法没有问题啊啊,这是一点,呃,如果说呢,你要是有这个外尔子句的话呢,需要去做一个筛选啊,啊那时候你就该筛选,那你筛选的就筛选,如果没有Y尔子句呢,我们就是对这个表中的这个所有的数据好呢,进行这个统计是吧?哎,这是我们说的这个点啊好,接下来我们看这个啊呃,下边这块呢,我们要说明的点是什么呢?就是说这哥俩呢,它的这个呃时间的话呢,基本上是一致的啊基本上是一致的啊,可能会略有差别是吧?呃,基本一致呢,它的复杂度是多少呢?这时候我们就要考虑你是用哪一个存储引擎了。
05:24
呃,如果呢,我们使用的是这个MYS这个存储引擎,我们说呀,这个统计表的这个行数呢,诶,它是OE这样的一个复杂度,相当于是个常量级别的复杂度,如果呢,你要使用的是这个诺DB的话呢,它就是需要进行一个全表的扫描了啊,相当于就是个on级别的一个复杂度了。啊,全面扫描,嗯,这个我加一个啊是。诶,这个逗号一下,哎,是。诶,写不出来了啊O。N。哎,它的这个复杂度啊,这个没写啊。好,那么他俩的话呢,是不是就有很大的一个区别了,那这里边呢,我们肯定就要问说为什么他们俩会有这样的一个区别,主要原因呢,是因为咱们这个MYS这个数据表呢,呃,它呢有一个Meta的信息记录了一下,我们这个表中的一个记录数啊,叫做roll啊,因为它有这样的一个记录呢,所以说我们这时候呢,呃,直接呢,你在查询的时候呢,它就直接把这个值呢给取出来了。
06:21
啊,那这时候呢,它的一致性呢,是由这个表极锁来保定啊,这个保证的它的力度呢,其实是比较粗一些的啊呃,你访问这个表的话呢,是一个表及锁的方式,所以呢,它就有机会啊,是可以选择这种方式呢,去做一个记录,而我们这个诺DB呢,因为它是支持事物的,支持这个机锁和ma这样的机制,所以呢,我们没有办法像麦S一样啊,它就维护这样变量了。啊,这是出于我们数据一致性的这样的一个考虑哈,诶它呢是这力度更小,并发性呢会更好一些是吧?诶但是的话,它的问题就是不能够去使用这样的变量啊,后边呢,咱们再去讲这个所谓的行基索和macc这个机制啊,所以呢,它只能是扫描全表,那复杂度呢,就是on了,通过这个循环加技术的方式呢去统计完成。
07:03
啊,这个大家注意一下,好,这呢我们说清楚了,就是哎他们俩是吧,哎它俩呢基本一样,但是在不同的存储引擎当中呢,它这个性能呢是有区别的。然后的话呢,我们再来看一看,在这个DB这个引擎当中,说这个countt具体字段啊,来统计这个行数的时候呢,这个靠不靠谱是吧?诶我们说呢,如果你这个抗的具体字段的话呢,说尽量呢,大家采用这个二级索引,那洋IG呢,是不是不建议我们使用主键索引,或者叫聚促索引,对吧?哎,为什么呢?因为你要使用这个主键这个居子索引的话呢,你需要把这个居子索引呢,相当于这个诶B加数,你这个对应的数据是不是就都加载到内存当中,因为呢,我们这个句子索引呢,它的叶子节点呢,是不是就放的我们一条条真实的这个记录了,它这个字段呢,肯定会更多啊,那你加载到内存中的时候呢,是不是占用的内存就会更大一些,而我们这个二级索引的话呢,因为它呃叶子节点呢,是放在你这个索引和我们这个主键,诶它这个数据量是不是更小一些,所以你加载的时候呢,是不是成本就会更低一些,所以呢,我们会选用这个二级索引。
08:04
啊,这是这个事儿,诶对于说我们这个抗氢和这个COUNT1来讲啊,如果呢,我们没有写明说具体你用哪个字段的话呢,诶这哥俩的话呢,它会自动的去选择一个空间比较小的二级缩业。啊,诶这时候就提到说自动选一个比较小的,那也就是说呢,我们这个表中呢,有多个二级索引的话呢,它到底应该选哪一个对吧?诶选哪一个的话呢,他说会选择占用空间最小的,首先呢,呃,这个呢,你可以理解成是针对我们居速索引来讲,它不会选择居住索引,而是选择呢占用空间最小的二级索引。啊,那要是二级索引有多个呢,它还是叫哎占用空间最小的二级索引,哎那这时候呢,它会针对于这个叫KS啊咱们讲这个,呃,讲这个plan的时候呢,其实是有个字段呢,叫做KS是吧?诶选这个比较小的一个二级所引呢,进行一个扫描,因为这个呢,成本是不是更低一些啊啊你像我们有时候这个看这index它的呢,它是一个五啊有的是十,有的呢来个63,你这个呢,显然是不是就加载的还有字符串了,就也会多,诶就是二级索引之间的话呢,也有哪个会更少,我们选的那个比较小的那个。
09:06
OK啊,应该我说清楚了啊。好,然后呢,我们再看一下这个叫select氢,咱们其实呢,直观上有这个感觉,说咱们在呃,写这个查询句的时候呢,大家尽量呢,不要去写这个select氢。对吧,诶尽量不要去写这个select星,因为呢,首先呢,你可能从这个直观上来感觉,你也不知道这个表到底有哪些字段啊,你想要哪个呢,你就写哪个就行,你不要用这个c select星,对吧?呃,那么往里边去深究,说我们为什么不建议去用呢?诶这块呢,我写了两个原因,第一个就是咱们在这个解析的过程当中啊,你写的是个星,你感觉挺省事的,但是我们在底层的查询过程当中啊,它首先呢,要把这个星呢,转化成具体的这个表中的字段。他就需要呢,查询我们这个数据字典,就我们系统的这些表,把你这个星呢转化成这个表中具体的列名啊,咱们在前面呢讲这个章节的时候呢,是不是提到过那个系统那些表了,对吧?诶在那些表里边是不是就储存了我们诶相记录的啊,你用户的定义的这些表啊里边的诶是不是那些具体的字段了是吧?诶你要查询这个具体的呃数据字典这个呢,肯定要浪费时间,而且这个时间呢花的还挺多啊,这是一个另外一个的话呢,由于你使用的叫select星,咱们在前面呢讲这个呃这个order buy的时候是吧,大家也看到了,很多时候呢,是不是我们呃写了这个orderba里边呢,对应的也有这个具体的这个呃索引是吧,但是呢,它就是不用,呃,就是因为你用这个氢的时候呢,我们根本没有办法呢,是不是使用这个叫。
10:29
啊,覆盖索引啊,啊,咱们当时讲这个例子的时候呢,是不是就说的这个事儿是吧,哎,你要是呢,有这个具体的字段的时候呢,诶我们反而能用上这个,就这个覆盖索引啊更好一点,用星呢就用不上了。啊哎,这呢,就是我们说的另外的一个点啊,这个呢也说清楚了。好,再说一个点呢,就是关于这个LIMIT1对这个优化的一个影响啊说LIMIT1的话呢,呃,对优化有没有影响呢?呃,这个呢,你得看怎么讲了,说如果呢,我们针对的是全表的一个扫描。啊,你要是全表的一个扫描的话呢,这时候我们加上一个LIMIT1啊,就是你确定了你结果集当中只有这一条记录啊,诶这时我们加个LIMIT1的话呢,是不是就意味着我们找到一条记录之后呢,就不再继续扫描了,哎,速度呢确实会加快。
11:10
但是如果说你针对这个字段呢,已经建立这个唯一索引了,那就没必要了啊,因为呢,你唯一索引呢,我已经找到一条记录了啊,那你这时候呢,本身的这个索引呢,就不再去往后再去查找了,这时候你加里音呢,其实意义也就不大了。啊,如果面试的时候呢,我要是面试官,我可能就会问这样的几个问题啊,一个是他,一个是他,一个是他。诶,我就要看看你对这个数据库啊,到底理解是有多么深刻啊,我把这个答案呢,都罗列到这儿了啊,然后下边这个点的话呢,大家可能都能够想得到的啊,就是我们在这个写程序的时候呢,尽量呢是不是差不多了啊,你觉得呢,呃,能够构成,其实呢,也算是构成一个事物了啊,我们呢,就可以呢,把这个数据呢做一个提交啊,能够提高这个性能啊,为什么呢?为什么会提高性能啊,当然这个呢,也可以作为一个面试的问题啊,可以去问的啊,那这时候呢,我们要谈的就是commit呢,会释放相关的一些资源,对吧?第一个呢,就是我们这个回滚段啊上用于恢复数据的信息啊,其实我们就会对应在那个安度日志当中啊,再呢,被程序语句获得这个锁啊,我们在这个提交这个事物啊之前啊,你相应的会有一些锁的一些获取,你提交以后呢,一个锁的资源相应的就释放了啊,还有这个锐度啊。
12:20
啊,这我写这个安度了,其实也涉及到这个回滚的这个情况了啊,锐度安度这个日志空间的一个开始释放。啊,以及呢,我们管理上述三种资源的这个内部的一个花费。啊,那把它呢,我们说经常去提交这个事儿呢,大家应该是比较清晰的,当然前提的话呢,你是该提交的话,那你提交了跟不提交有区别,那有时候你要不该提交,那你就别乱提交啊,一旦提交呢,我们的事务就结束了,对吧。好,那这呢,我们把这几个零散的点呢,就给大家说了说,哎,相对来说对大家这个面试当中我觉得会有一些帮助。
我来说两句