绝了,通俗的给你讲懂MySQL表连接原理
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">你<span style="color: black;">晓得</span>的越多,不<span style="color: black;">晓得</span>的就越多,业余的像一棵小草!</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">你来,<span style="color: black;">咱们</span><span style="color: black;">一块</span>精进!你不来,我和你的竞争对手<span style="color: black;">一块</span>精进!</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">编辑:业余草</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">liuchenyang0515.blog.csdn.net</span></p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">举荐</span>:https:/</span><span style="color: black;">/www.xttblog.com/?p=5317</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rh6mJGicq6I0ElfeaiaG7jyzZjCt8au3X11YCxt1XGibP7MADEL9CoZeibUw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">1、</span>表连接的简介</span></h2><span style="color: black;">create</span> <span style="color: black;">table</span> t1(m1 <span style="color: black;">int</span>, n1<span style="color: black;">char</span>(<span style="color: black;">1</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">));</p><span style="color: black;">create</span> <span style="color: black;">table</span> t2(m2 <span style="color: black;">int</span>, n2 <span style="color: black;">char</span>(<span style="color: black;">1</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">));</p><span style="color: black;">insert</span> <span style="color: black;">into</span> t1 <span style="color: black;">values</span>(<span style="color: black;">1</span>,<span style="color: black;">a</span>),(<span style="color: black;">2</span>,<span style="color: black;">b</span>),(<span style="color: black;">3</span>,<span style="color: black;">c</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> t2 <span style="color: black;">values</span>(<span style="color: black;">2</span>,<span style="color: black;">b</span>),(<span style="color: black;">3</span>,<span style="color: black;">c</span>),(<span style="color: black;">4</span>,<span style="color: black;">d</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">t1表数据如下</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhKnpwrYlxibCHHPpHdicwic1MDWYfnfPS2E7Okvw14356uCcf1LRPqbvMw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">t2表数据如下</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhqBR0HakeApHfibZUFMibvc6vQFNvpmlXJTAvFGVrllFXNgpw30yQxicFg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span><span style="color: black;">晓得</span>,<span style="color: black;">所说</span>表连接<span style="color: black;">便是</span>把各个表中的记录都取出来进行依次匹配,最后把匹配组合的记录<span style="color: black;">一块</span>发送给客户端。<span style="color: black;">例如</span>下面把t1表和t2表连接起来的过程如下图</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhjZEQWUGjLThgvHQ6kQdgrwRxSkP1FGVfNyEvwu3UO0H5o72lexwZZg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「什么是连接<span style="color: black;">查找</span>?」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">例如</span>上面t1和t2表的记录连接起来<span style="color: black;">构成</span>一个新的更大的记录,这个<span style="color: black;">查找</span>过程就<span style="color: black;">叫作</span>为连接<span style="color: black;">查找</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「什么是笛卡尔积?」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>连接<span style="color: black;">查找</span>的结果集中<span style="color: black;">包括</span>一个表中的每一条记录与另一个表中的每一条记录相互匹配组合的记录,<span style="color: black;">那样</span><span style="color: black;">这般</span>的结果集就<span style="color: black;">能够</span><span style="color: black;">叫作</span>为笛卡尔积。</p><span style="color: black;"># 这三者效果<span style="color: black;">同样</span>,只要不写<span style="color: black;">要求</span>,就产生笛卡尔积,结果集的数量<span style="color: black;">同样</span>。</span><span style="color: black;">select</span> * <span style="color: black;">from</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t1, t2;</p><span style="color: black;"># 内连接</span><span style="color: black;">select</span> * <span style="color: black;">from</span> t1 <span style="color: black;">inner</span> <span style="color: black;">join</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t2;</p><span style="color: black;"># 全连接</span><span style="color: black;">select</span> * <span style="color: black;">from</span> t1 <span style="color: black;">cross</span> <span style="color: black;">join</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t2;</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rheRDywecG7icvBzBF2IPPhQC15wzwuZEs69Ab2icDpspHOy9bREW1WetA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">表t1中有3条记录,表t2中<span style="color: black;">亦</span>有3条记录,两个表连接后的笛卡尔积就有3 x 3 = 9条记录,只要把两个表的记录数相乘,就能得到笛卡尔积的数量。</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">2、</span>表连接的过程</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">笛卡尔积<span style="color: black;">亦</span>是一个很大的问题,不加限制<span style="color: black;">要求</span>,结果集的数量就会很大。<span style="color: black;">例如</span>你在<span style="color: black;">研发</span>过程中<span style="color: black;">必须</span>2个表的连接,表1有20000条记录,表2有10000条记录,表3有100条记录,<span style="color: black;">那样</span>3张表连接后产生的笛卡尔积就有20000 x 10000 x 100 = 20000000000条记录(两百亿条记录)。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此</span>在连接时过滤掉特定的记录组合是<span style="color: black;">特别有</span>必要的,为了避免笛卡尔积,<span style="color: black;">必定</span>要在表连接的时候加上<span style="color: black;">要求</span>!</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">下面来看一下有过滤<span style="color: black;">要求</span>的表连接的执行过程。</p><span style="color: black;"># 下面两种写法都<span style="color: black;">同样</span>,执行效率<span style="color: black;">无</span>区别,<span style="color: black;">瞧瞧</span>自己习惯于哪种写法</span><span style="color: black;">select</span> * <span style="color: black;">from</span> t1 <span style="color: black;">join</span> t2 <span style="color: black;">on</span> t1.m1 > <span style="color: black;">1</span> <span style="color: black;">and</span> t1.m1 = t2.m2 <span style="color: black;">and</span> t2.n2 < <span style="color: black;">d</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p><span style="color: black;">select</span> * <span style="color: black;">from</span> t1, t2 <span style="color: black;">where</span> t1.m1 > <span style="color: black;">1</span> <span style="color: black;">and</span> t1.m1 = t2.m2 <span style="color: black;">and</span> t2.n2 < <span style="color: black;">d</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>:先说明<span style="color: black;">要求</span>的概念,要区分什么是<strong style="color: blue;">「连接<span style="color: black;">要求</span>」</strong>和<strong style="color: blue;">「过滤<span style="color: black;">要求</span>」</strong>!!</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「连接<span style="color: black;">要求</span>」</strong>是针对两张表而言的,<span style="color: black;">例如</span>t1.m1 = t2.m2、t1.n1 > t2.n2,表达式两边是两个表的字段比较。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「过滤<span style="color: black;">要求</span>」</strong>是针对单表而言的,<span style="color: black;">例如</span>t1.m1 > 1是针对t1表的过滤<span style="color: black;">要求</span>,t2.n2 < d是针对t2表的过滤<span style="color: black;">要求</span>。</p><span style="color: black;">首要</span>确定<span style="color: black;">第1</span>个<span style="color: black;">必须</span><span style="color: black;">查找</span>的表,这个表<span style="color: black;">叫作</span>之为<strong style="color: blue;">「驱动表」</strong>。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在单表中<span style="color: black;">选取</span>代价最小的<span style="color: black;">查找</span>方式,简单理解<span style="color: black;">便是</span>走合适的索引<span style="color: black;">就可</span>。此处假设<span style="color: black;">运用</span>t1<span style="color: black;">做为</span>驱动表,<span style="color: black;">那样</span>就<span style="color: black;">必须</span>到t1表中找满足过滤<span style="color: black;">要求</span>t1.m1 > 1的记录,<span style="color: black;">由于</span>表中的数据太少,<span style="color: black;">咱们</span><span style="color: black;">亦</span>没在表上<span style="color: black;">创立</span>索引,<span style="color: black;">因此</span>此处<span style="color: black;">查找</span>t1表的<span style="color: black;">查找</span>的方式<span style="color: black;">便是</span>all,<span style="color: black;">亦</span><span style="color: black;">便是</span>采用全表扫描的方式执行单表<span style="color: black;">查找</span>,筛选出符合<span style="color: black;">要求</span>的驱动表记录。</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhtgFOAXITMHYbp4bPibmIzwQvStkZ4eZY4DsHsqgT5UEcntCiciaUMYpxA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这儿</span>筛选出来的t1驱动表记录有2条。</p>从第1步中驱动表筛选出来的每一条记录,都要到t2表中<span style="color: black;">查找</span>匹配记录。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">匹配记录<span style="color: black;">便是</span>找到满足连接<span style="color: black;">要求</span>和过滤<span style="color: black;">要求</span>的记录。<span style="color: black;">由于</span>是<span style="color: black;">按照</span>t1表中的记录去找t2表中的记录,<span style="color: black;">因此</span>t2表<span style="color: black;">亦</span><span style="color: black;">能够</span><span style="color: black;">叫作</span>为<strong style="color: blue;">「被驱动表」</strong>。上一步从驱动表筛选出了2条记录,<span style="color: black;">寓意</span>着<span style="color: black;">必须</span>从头到尾将t2表<span style="color: black;">查找</span>2次,此时就得看两表之间的连接<span style="color: black;">要求</span>了,<span style="color: black;">这儿</span><span style="color: black;">便是</span>t1.m1 = t2.m2。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>从t1表<span style="color: black;">查找</span>得到的<span style="color: black;">第1</span>条记录,而这条记录t1.m1=2,<span style="color: black;">按照</span>连接<span style="color: black;">要求</span>t1.m1 = t2.m2,就相当于在t2表加上过滤<span style="color: black;">要求</span>t2.m2 = 2,此时t2表相当于有了两个过滤<span style="color: black;">要求</span>t2.m2 = 2 and t2.n2 < d,<span style="color: black;">而后</span>到t2表执行单表<span style="color: black;">查找</span>,每当匹配到满足<span style="color: black;">要求</span>的一条记录后立即返回给MySQL客户端,以此类推。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此</span><span style="color: black;">全部</span>连接<span style="color: black;">查找</span>的执行过程如下:</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhp4ep2SupxibEsAszxDlkMPD905PCqLsaniad05DaNyhfzjkLxPtccajw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最后连接<span style="color: black;">查找</span>的结果<span style="color: black;">仅有</span>2条记录。</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rh9fLXAoQvlWNxSic9diaMQRNziaoNxJgMxTtEdG7cU0stt0H5rDFBhlWfg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>把t1.m1 > 1这个过滤<span style="color: black;">要求</span>去掉了,<span style="color: black;">那样</span>从t1表查出的记录就有3条,就<span style="color: black;">必须</span>从头到尾扫3次t2表了。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「其实这个流程的<span style="color: black;">招数</span><span style="color: black;">便是</span>用伪代码说明非常合适,你细品,看懂这个伪代码,你就理解了表连接的<span style="color: black;">过程</span>。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">for 筛选 驱动表 满足<span style="color: black;">要求</span>的每条记录 {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> for 筛选 被驱动表 满足<span style="color: black;">要求</span>的每条记录 {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> 发送到MySQL客户端;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">从这个伪代码<span style="color: black;">能够</span>看出,驱动表的每一条记录都会尝试遍历被驱动表的每条记录并匹配连接,每成功连接一条就返回给MySQL客户端。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">总结:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在两表连接<span style="color: black;">查找</span>中,驱动表只需<span style="color: black;">拜访</span>一次,而被驱动表可能<span style="color: black;">必须</span><span style="color: black;">拜访</span>多次。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">并不是将所有满足过滤<span style="color: black;">要求</span>的驱动表记录先<span style="color: black;">查找</span>出来放到一个<span style="color: black;">地区</span>,<span style="color: black;">而后</span>再去被驱动表<span style="color: black;">查找</span>的(<span style="color: black;">由于</span><span style="color: black;">倘若</span>满足过滤<span style="color: black;">要求</span>的驱动表很大,<span style="color: black;">必须</span>的临时存储空间就会非常大)。而是每<span style="color: black;">得到</span>一条满足过滤<span style="color: black;">要求</span>的驱动表记录,就立即到被驱动表中<span style="color: black;">查找</span>匹配的记录。</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">3、</span>内连接和外连接</span></h2>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">1.内连接</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">上面第二节所讲的,都是内连接。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">先<span style="color: black;">创立</span>2张表,后续<span style="color: black;">按照</span>这2张表来讲解。</p><span style="color: black;">CREATE</span> <span style="color: black;">TABLE</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> student (</p> stu_no <span style="color: black;">INT</span> <span style="color: black;">NOT</span> <span style="color: black;">NULL</span> AUTO_INCREMENT <span style="color: black;">COMMENT</span> <span style="color: black;">学号</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p> <span style="color: black;">name</span> <span style="color: black;">VARCHAR</span>(<span style="color: black;">5</span>) <span style="color: black;">COMMENT</span> <span style="color: black;">姓名</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p> major <span style="color: black;">VARCHAR</span>(<span style="color: black;">30</span>) <span style="color: black;">COMMENT</span> <span style="color: black;">专业</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p> PRIMARY <span style="color: black;">KEY</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> (stu_no)</p>) <span style="color: black;">Engine</span>=<span style="color: black;">InnoDB</span> <span style="color: black;">CHARSET</span>=utf8mb4 <span style="color: black;">COMMENT</span> <span style="color: black;">学生信息表</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p><span style="color: black;">CREATE</span> <span style="color: black;">TABLE</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> score (</p> stu_no <span style="color: black;">INT</span> <span style="color: black;">COMMENT</span> <span style="color: black;">学号</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p> subject <span style="color: black;">VARCHAR</span>(<span style="color: black;">30</span>) <span style="color: black;">COMMENT</span> <span style="color: black;">科目</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p> score <span style="color: black;">TINYINT</span> <span style="color: black;">COMMENT</span> <span style="color: black;">成绩</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">,</p> PRIMARY <span style="color: black;">KEY</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> (stu_no, subject)</p>) <span style="color: black;">Engine</span>=<span style="color: black;">InnoDB</span> <span style="color: black;">CHARSET</span>=utf8mb4 <span style="color: black;">COMMENT</span> <span style="color: black;">学生成绩表</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">插进</span><span style="color: black;">有些</span>数据</p><span style="color: black;">insert</span> <span style="color: black;">into</span> student <span style="color: black;">values</span>(<span style="color: black;">20210901</span>, <span style="color: black;">王大个</span>, <span style="color: black;">软件工程</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> student <span style="color: black;">values</span>(<span style="color: black;">20210902</span>, <span style="color: black;">刘帅哥</span>, <span style="color: black;">物联网工程</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> student <span style="color: black;">values</span>(<span style="color: black;">20210903</span>, <span style="color: black;">张小伟</span>, <span style="color: black;">电子工程</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> score <span style="color: black;">values</span>(<span style="color: black;">20210901</span>, <span style="color: black;">数据结构</span>, <span style="color: black;">92</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> score <span style="color: black;">values</span>(<span style="color: black;">20210901</span>, <span style="color: black;">计算机网络</span>, <span style="color: black;">94</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> score <span style="color: black;">values</span>(<span style="color: black;">20210902</span>, <span style="color: black;">计算机网络</span>, <span style="color: black;">88</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p><span style="color: black;">insert</span> <span style="color: black;">into</span> score <span style="color: black;">values</span>(<span style="color: black;">20210902</span>, <span style="color: black;">数据结构</span>, <span style="color: black;">80</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">student表数据如下:</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rh57wPua2tCuLlmff56ibl0DHo3k4Wstfky19p5V291IvsNHblbBgXrHg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">score表数据如下:</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rh7zGx9FJwps3lHdibHhfIkd8BF6VCnZw5ibQlvCB4gvUcTyZMRG9TPB9Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>想要把学生的成绩都查出来,就<span style="color: black;">必须</span>表连接(score表中<span style="color: black;">无</span>姓名,<span style="color: black;">因此</span><span style="color: black;">不可</span>只查score表),连接过程<span style="color: black;">便是</span>从student表取出记录,<span style="color: black;">而后</span>在score表中<span style="color: black;">查询</span>number相同的成绩记录,连接<span style="color: black;">要求</span>是student.stu_no= score.stu_no;</p><span style="color: black;">select</span> * <span style="color: black;">from</span> student <span style="color: black;">join</span> score <span style="color: black;">where</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> student.stu_no = score.stu_no;</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhZAlK0jGygnexyAmbz6RNaxnKWF0deShoBImia50q92K1lGuFtYjtBUQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">表连接的<span style="color: black;">所有</span>字段就在这里了,字段有点多,stu_no是重复的,<span style="color: black;">咱们</span>修改一下</p><span style="color: black;">select</span> s1.stu_no, s1.name, s2.subject, s2.score <span style="color: black;">from</span> student <span style="color: black;">as</span> s1 <span style="color: black;">join</span> score <span style="color: black;">as</span> s2 <span style="color: black;">on</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> s1.stu_no = s2.stu_no;</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rh52fYu865r3YbZ7xzcEZAcdhODIwTib5pVPGdCZKVlZB9owaDTiaX3wHg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到,学生的各科成绩都被查出来了。<span style="color: black;">然则</span>张小伟(学号为20210903的<span style="color: black;">朋友</span>)<span style="color: black;">由于</span>缺考,在score表中<span style="color: black;">无</span>记录。要是老师想查看所有学生的成绩(<span style="color: black;">包含</span>缺考的<span style="color: black;">朋友</span>)该怎么办呢?<span style="color: black;">亦</span><span style="color: black;">便是</span>说,哪怕成绩为空,<span style="color: black;">亦</span>要<span style="color: black;">表示</span>这位<span style="color: black;">朋友</span>在这个表里面,咱们<span style="color: black;">不可</span>把他给踢了吧!</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「这个问题就化为这个模型:<span style="color: black;">针对</span>驱动表中的某条记录,哪怕<span style="color: black;">按照</span>连接<span style="color: black;">要求</span><span style="color: black;">或</span>过滤<span style="color: black;">要求</span>在被驱动表中<span style="color: black;">无</span>找到对应的记录,<span style="color: black;">亦</span>还是要把该驱动表的记录加到结果集。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这<span style="color: black;">便是</span>内连接的局限性。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「其实<span style="color: black;">咱们</span>想要看到的结果集是<span style="color: black;">这般</span>的」</strong></p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhc60P3I58iaFicFzzXjZK6cphNyF5W71eNNCaJT41p7yFPd6U3ZjMwkYA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">为<span style="color: black;">认识</span>决这个问题,就有了<strong style="color: blue;">「内连接」</strong>和<strong style="color: blue;">「外连接」</strong>的区别。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>内连接<span style="color: black;">来讲</span>,若驱动表中的记录<span style="color: black;">根据</span><strong style="color: blue;">「连接<span style="color: black;">要求</span><span style="color: black;">或</span>过滤<span style="color: black;">要求</span>」</strong>在被驱动表中找不到匹配的记录,则该记录不会加入到最后的结果集。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">前面<span style="color: black;">说到</span>的都是内连接,<span style="color: black;">例如</span>前面例子中,当t1.m1 = 2时,<span style="color: black;">按照</span>连接<span style="color: black;">要求</span>t1.m1 = t2.m2,在被驱动表中<span style="color: black;">倘若</span><span style="color: black;">无</span>记录满足过滤<span style="color: black;">要求</span>t2.m2 = 2 and t2.n2 < d,驱动表的记录就不会加到最后的结果集。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>:<span style="color: black;">咱们</span>说过,内连接语法有<span style="color: black;">非常多</span>种。<span style="color: black;">针对</span>内连接<span style="color: black;">来讲</span>,连接<span style="color: black;">要求</span><span style="color: black;">选取</span>on<span style="color: black;">或</span>where都<span style="color: black;">能够</span>,凡是不符合on子句<span style="color: black;">或</span>where子句<span style="color: black;">要求</span>的记录都会被过滤掉,不会被连接,更不会在最后的结果集。</p><span style="color: black;"># 以下三者效果<span style="color: black;">同样</span>,当用join进行内连接时,<span style="color: black;">要求</span>用on<span style="color: black;">或</span>where连接都<span style="color: black;">能够</span>。</span><span style="color: black;">select</span> * <span style="color: black;">from</span> student <span style="color: black;">join</span> score <span style="color: black;">on</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> student.stu_no= score.stu_no;</p><span style="color: black;">select</span>*<span style="color: black;">from</span> student <span style="color: black;">join</span> score <span style="color: black;">where</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> student.stu_no= score.stu_no;</p><span style="color: black;">select</span> * <span style="color: black;">from</span> student, score <span style="color: black;">where</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> student.stu_no= score.stu_no;</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">2.外连接</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>外连接<span style="color: black;">来讲</span>,即使驱动表中的记录<span style="color: black;">根据</span><strong style="color: blue;">「连接<span style="color: black;">要求</span>和过滤<span style="color: black;">要求</span>」</strong>在被驱动表中找不到匹配的记录,该记录<span style="color: black;">亦</span>仍然<span style="color: black;">必须</span>加入到结果集。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>外连接<span style="color: black;">来讲</span>,又有左(外)连接和右(外)连接的区别</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">左(外)连接:<span style="color: black;">选择</span>左侧的表为驱动表。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">右(外)连接:<span style="color: black;">选择</span>右侧的表为驱动表。</p><span style="color: black;">❝</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「重点强调:<span style="color: black;">针对</span>内连接<span style="color: black;">来讲</span>,<span style="color: black;">选择</span>哪个表为驱动表都<span style="color: black;">不碍事</span>。而外连接的驱动表是固定的,左(外)连接的驱动表<span style="color: black;">便是</span>左边那个表,右(外)连接的驱动表<span style="color: black;">便是</span>右边那个表。」</strong></p><span style="color: black;">❞</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「左(外)连接的语法:」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">例如</span>要把t1表和t2表进行左连接<span style="color: black;">查找</span>。</p><span style="color: black;">select</span> * <span style="color: black;">from</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t1 </p><span style="color: black;">left</span> [<span style="color: black;">outer</span>] <span style="color: black;">join</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t2</p><span style="color: black;">on</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> <span style="color: black;">要求</span></p>[<span style="color: black;">where</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> 普<span style="color: black;">经过</span>滤<span style="color: black;">要求</span>]</p><span style="color: black;"># <span style="color: black;">重视</span>这个on<span style="color: black;">要求</span><span style="color: black;">包含</span>连接<span style="color: black;">要求</span>和驱动表与被驱动表的单表过滤<span style="color: black;">要求</span>。</span><span style="color: black;"># []括号<span style="color: black;">表率</span><span style="color: black;">能够</span>省略</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">左表所有记录都会有,右表<span style="color: black;">无</span>与之匹配的则用NULL填充。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>外连接<span style="color: black;">来讲</span>,on和where是有区别的。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">即使被驱动表中的记录<span style="color: black;">没法</span>匹配on子句的<span style="color: black;">要求</span>,该驱动表的记录仍然是满足<span style="color: black;">要求</span>的一条记录,对应被驱动表的各个字段用NULL填充。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「简言之,<span style="color: black;">针对</span>外连接,驱动表的记录<span style="color: black;">必定</span>都有,被驱动表不匹配就用NULL填充。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">而where过滤<span style="color: black;">要求</span>是在记录连接过后的普<span style="color: black;">经过</span>滤<span style="color: black;">要求</span>,即连接的记录会再次判断<span style="color: black;">是不是</span>符合<span style="color: black;">要求</span>,不符合就从结果集中剔除。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">回到<span style="color: black;">刚才</span>的问题,要把所有学生成绩<span style="color: black;">表示</span>出来(<span style="color: black;">包含</span>缺考的学生)</p><span style="color: black;">select</span> s1.stu_no, s1.name, s2.subject, s2.score <span style="color: black;">from</span> student <span style="color: black;">as</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> s1 </p><span style="color: black;">left</span> <span style="color: black;">join</span>score<span style="color: black;">as</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> s2 </p><span style="color: black;">on</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> s1.stu_no = s2.stu_no;</p><img src="https://mmbiz.qpic.cn/mmbiz_png/TLH3CicPVibrfFcTPRKJMsNlRWGmJxH5rhc60P3I58iaFicFzzXjZK6cphNyF5W71eNNCaJT41p7yFPd6U3ZjMwkYA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">从上面结果集<span style="color: black;">能够</span>看出,虽然张小伟缺考,<span style="color: black;">然则</span>还是在结果集中,只<span style="color: black;">不外</span>对应的科目成绩用NULL填充。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「右(外)连接的语法」</strong></p><span style="color: black;">select</span> * <span style="color: black;">from</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t1 </p><span style="color: black;">right</span> [<span style="color: black;">outer</span>] <span style="color: black;">join</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> t2</p><span style="color: black;">on</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> <span style="color: black;">要求</span></p>[<span style="color: black;">where</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> 普<span style="color: black;">经过</span>滤<span style="color: black;">要求</span>]</p><span style="color: black;"># <span style="color: black;">重视</span>这个on<span style="color: black;">要求</span><span style="color: black;">包含</span>连接<span style="color: black;">要求</span>和驱动表与被驱动表的单表过滤<span style="color: black;">要求</span>。</span><span style="color: black;"># []括号<span style="color: black;">表率</span><span style="color: black;">能够</span>省略</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">右连接中,驱动表是右边的表,被驱动表是左边的表,右表所有记录都会有,左表<span style="color: black;">无</span>与之匹配的则用NULL填充。<span style="color: black;">这儿</span>就不举例了。</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">4、</span>表连接的原理</span></h2>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">1.简单的嵌套循环连接(Simple Nested-Loop Join)</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span>前边说过,<span style="color: black;">针对</span>两表连接<span style="color: black;">来讲</span>,驱动表只会<span style="color: black;">拜访</span>一遍,但被驱动表要被<span style="color: black;">拜访</span>到好多遍,<span style="color: black;">详细</span><span style="color: black;">拜访</span>几遍取决于驱动表执行单表<span style="color: black;">查找</span>后满足<span style="color: black;">要求</span>的记录条数。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">假设t1表和t2表都<span style="color: black;">无</span>索引,t1表和t2表内连接的大致过程如下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">过程</span>1:<span style="color: black;">选择</span>驱动表t1,<span style="color: black;">运用</span>与驱动表t1<span style="color: black;">关联</span>的过滤<span style="color: black;">要求</span>,<span style="color: black;">选择</span>成本最低的单表<span style="color: black;">拜访</span><span style="color: black;">办法</span>来执行对驱动表的单表<span style="color: black;">查找</span>。(<span style="color: black;">按照</span>你的索引和记录数量,<span style="color: black;">查找</span>优化器会<span style="color: black;">选取</span>成本最低的<span style="color: black;">拜访</span><span style="color: black;">办法</span>,<span style="color: black;">这儿</span><span style="color: black;">无</span>索引则全表扫描)</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">过程</span>2:对上一步中<span style="color: black;">查找</span>驱动表得到的每一条满足<span style="color: black;">要求</span>的记录,都分别到被驱动表t2中<span style="color: black;">查询</span>匹配的记录。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">详细</span>细节在第二节说过,<span style="color: black;">这儿</span>就不细致展开。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>有第3个表t3进行连接的话,<span style="color: black;">那样</span>总体<span style="color: black;">查找</span>过程<span style="color: black;">便是</span>,<span style="color: black;">查询</span>t1表满足单表过滤<span style="color: black;">要求</span>的<span style="color: black;">第1</span>条记录,匹配连接t2表满足单表过滤<span style="color: black;">要求</span>的<span style="color: black;">第1</span>条记录(此时驱动表是t1,被驱动表是t2),<span style="color: black;">而后</span>匹配连接t3表满足单表过滤<span style="color: black;">要求</span>的第1条记录(此时驱动表是t2,被驱动表是t3),将这条满足所有<span style="color: black;">要求</span>的一条记录返回给MySQL客户端;前面<span style="color: black;">要求</span>不变,接着匹配连接t3表满足单表过滤<span style="color: black;">要求</span>的第2条记录…</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这个过程最适合用伪代码<span style="color: black;">来讲</span>明了</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">for 筛选t1表满足<span style="color: black;">要求</span>的每条记录 {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> for 筛选t2表满足<span style="color: black;">要求</span>的每条记录 {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> for 筛选t3表满足<span style="color: black;">要求</span>的每条记录 {</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> 发送到MySQL客户端;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这个过程就像是一个嵌套的循环,驱动表每一条记录,都要从头到尾扫描一遍被驱动表去尝试匹配。这种连接执行方式<span style="color: black;">叫作</span>之为简单的嵌套循环连接(Simple Nested-Loop Join),这是比较笨拙的一种连接<span style="color: black;">查找</span>算法。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>:<span style="color: black;">针对</span>嵌套循环连接算法<span style="color: black;">来讲</span>,每当从驱动表<span style="color: black;">得到</span>一条记录,就<span style="color: black;">按照</span>这条记录立即到被驱动表查一次,<span style="color: black;">倘若</span>得到匹配连接记录,那就把这条连接的记录立即发送给MySQL客户端,而不是等<span style="color: black;">查找</span>完所有结果后才返回。<span style="color: black;">而后</span>再到被驱动表获取下一条符合<span style="color: black;">要求</span>的记录,直到被驱动表遍历完成,就切换到驱动表的下一条记录再次遍历被驱动表的每条记录,以此类推。</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">2.基于索引的嵌套循环连接(Index Nested-Loop Join)</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在上一小节嵌套循环连接的<span style="color: black;">过程</span>2中可能<span style="color: black;">必须</span><span style="color: black;">拜访</span>多次被驱动表,<span style="color: black;">倘若</span><span style="color: black;">拜访</span>被驱动表的方式都是全表扫描,扫描次数就非常多。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">幸好MySQL优化器会找出所有<span style="color: black;">能够</span>用来执行该语句的<span style="color: black;">方法</span>,并会对比之后找出成本最低的<span style="color: black;">方法</span>,简单理解<span style="color: black;">便是</span><span style="color: black;">运用</span>哪个索引最好。<span style="color: black;">因此</span>既然会多次<span style="color: black;">拜访</span>被驱动表,索引好<span style="color: black;">欠好</span><span style="color: black;">便是</span>性能的瓶颈。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">查找</span>被驱动表其实就相当于一次单表扫描,<span style="color: black;">那样</span><span style="color: black;">咱们</span><span style="color: black;">能够</span>利用索引来加快<span style="color: black;">查找</span>速度。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">回到最<span style="color: black;">起始</span>介绍的t1表和t2表进行内连接的例子:</p><span style="color: black;">select</span> * <span style="color: black;">from</span> t1 <span style="color: black;">join</span> t2 <span style="color: black;">on</span> t1.m1 > <span style="color: black;">1</span> <span style="color: black;">and</span> t1.m1 = t2.m2 <span style="color: black;">and</span> t2.n2 < <span style="color: black;">d</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这其实是嵌套循环连接算法执行的连接<span style="color: black;">查找</span>,再把上边那个<span style="color: black;">查找</span>执行过程拿下来给<span style="color: black;">大众</span>看一下:</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">查找</span>驱动表t1后的结果集中有2条记录,嵌套循环连接算法<span style="color: black;">必须</span><span style="color: black;">查找</span>被驱动表2次:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当t1.m1 = 2时,去<span style="color: black;">查找</span>一遍t2表,对t2表的查询语句相当于:</p><span style="color: black;">select</span> * <span style="color: black;">from</span> t2 <span style="color: black;">where</span> t2.m2 = <span style="color: black;">2</span> <span style="color: black;">and</span> t2.n2 < <span style="color: black;">d</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当t1.m1 = 3时,再去<span style="color: black;">查找</span>一遍t2表,此时对t2表的<span style="color: black;">查找</span>语句相当于:</p><span style="color: black;">select</span> * <span style="color: black;">from</span> t2 <span style="color: black;">where</span> t2.m2 = <span style="color: black;">3</span> <span style="color: black;">and</span> t2.n2 < <span style="color: black;">d</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到,原来的t1.m1 = t2.m2这个<span style="color: black;">触及</span>两个表的过滤<span style="color: black;">要求</span>在针对t2表进行<span style="color: black;">查找</span>时,选出t1表的一条记录之后,t2表的<span style="color: black;">要求</span>就<span style="color: black;">已然</span>确定了,即t2.m2 = 常数值,<span style="color: black;">因此</span><span style="color: black;">咱们</span>只<span style="color: black;">必须</span>优化对t2表的<span style="color: black;">查找</span><span style="color: black;">就可</span>,<span style="color: black;">以上</span>两个对t2表的<span style="color: black;">查找</span>语句中利用到的列是m2和n2列,<span style="color: black;">咱们</span><span style="color: black;">能够</span>进行如下尝试:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在m2列上<span style="color: black;">创立</span>索引,<span style="color: black;">由于</span>对m2列的<span style="color: black;">要求</span>是等值<span style="color: black;">查询</span>,<span style="color: black;">例如</span>t2.m2 = 2、t2.m2 = 3等,<span style="color: black;">因此</span>可能<span style="color: black;">运用</span>到ref的<span style="color: black;">拜访</span><span style="color: black;">办法</span>,假设<span style="color: black;">运用</span>ref的<span style="color: black;">拜访</span><span style="color: black;">办法</span>去执行对t2表的<span style="color: black;">查找</span>的话,<span style="color: black;">必须</span>回表之后再判断t2.n2 < d这个<span style="color: black;">要求</span><span style="color: black;">是不是</span>成立。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在n2列上<span style="color: black;">创立</span>索引,<span style="color: black;">触及</span>到的<span style="color: black;">要求</span>是t2.n2 < d,可能用到range的<span style="color: black;">拜访</span><span style="color: black;">办法</span>,假设<span style="color: black;">运用</span>range的<span style="color: black;">拜访</span><span style="color: black;">办法</span>对t2表进行<span style="color: black;">查找</span>,<span style="color: black;">必须</span>在回表之后再判断在m2列的<span style="color: black;">要求</span><span style="color: black;">是不是</span>成立。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">假设m2和n2列上都存在索引,<span style="color: black;">那样</span>就<span style="color: black;">必须</span>从这两个里面挑一个代价更低的索引来<span style="color: black;">查找</span>t2表。<span style="color: black;">亦</span>有可能不<span style="color: black;">运用</span>m2和n2列的索引,<span style="color: black;">仅有</span>在非聚集索引 + 回表的代价比全表扫描的代价更低时才会<span style="color: black;">运用</span>索引。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Index Nested-Loop Join与Simple Nested-Loop Join的<span style="color: black;">区别</span><span style="color: black;">便是</span>被驱动表加了索引,后面只说Index Nested-Loop Join。</p><span style="color: black;">❝</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">扩展思考:假设驱动表全表扫描,行数是N,被驱动表走索引,行数是M。<span style="color: black;">那样</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1.每次在被驱动表查一行数据,则要先搜索索引,再回表<span style="color: black;">查询</span>主键索引。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2.每次被驱动表<span style="color: black;">查询</span>次数是以2为底的M的对数,记为log M,<span style="color: black;">因此</span>在被驱动表上查一行的扫描次数是 2*log M(<span style="color: black;">由于</span>要回表<span style="color: black;">查询</span>利用到主键索引)。驱动表执行过程就要扫描驱动表N行,<span style="color: black;">而后</span><span style="color: black;">针对</span>每一行,到被驱动表上匹配一次。<span style="color: black;">因此呢</span><span style="color: black;">全部</span>执行过程,<span style="color: black;">查询</span>的总次数是 N+N*2*log M。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3.显然N对扫描行数的影响更大,<span style="color: black;">因此呢</span>应该让小表来做驱动表。N扩大1000倍的话,扫描行数就会扩大 1000倍;而M扩大1000倍,扫描行数扩大不到10倍。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「总结:<span style="color: black;">倘若</span>被驱动表<span style="color: black;">能够</span><span style="color: black;">运用</span>索引,<span style="color: black;">那样</span>驱动表<span style="color: black;">必定</span>要<span style="color: black;">选取</span>数据量小的小表。」</strong></p><span style="color: black;">❞</span>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">3.基于块的嵌套循环连接(Block Nested-Loop Join)</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「扫描一个表的过程其实是先把这个表从磁盘上加载到内存中,<span style="color: black;">而后</span>从内存中比较匹配<span style="color: black;">要求</span><span style="color: black;">是不是</span>满足。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">实质</span><span style="color: black;">研发</span>中的表可不像t1、t2这种<span style="color: black;">仅有</span>3条记录,几千万<span style="color: black;">乃至</span>几亿条记录的表到处都是。<span style="color: black;">此刻</span>假设<span style="color: black;">咱们</span><span style="color: black;">不可</span><span style="color: black;">运用</span>索引加快被驱动表的<span style="color: black;">查找</span>过程,<span style="color: black;">因此</span><span style="color: black;">针对</span>驱动表的每一条记录,都<span style="color: black;">必须</span>对被驱动表进行全表扫描。而对被驱动表全表扫描时,可能表前面的记录还在内存中,表后边的记录可能还在磁盘上。等扫描到后边记录的时候,可能<span style="color: black;">因为</span>内存不足,<span style="color: black;">因此</span><span style="color: black;">必须</span>把表前面的记录从内存中释放掉给正在扫描的记录腾<span style="color: black;">地区</span>,<span style="color: black;">这般</span>就非常消耗性能。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">采用嵌套循环连接算法的两表连接过程中,被驱动表是要被<span style="color: black;">拜访</span>好多次的,<span style="color: black;">因此</span><span style="color: black;">咱们</span>得想办法,<strong style="color: blue;">「<span style="color: black;">尽可能</span>减少被驱动表的<span style="color: black;">拜访</span>次数。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「驱动表中满足筛选<span style="color: black;">要求</span>的有多少条记录,就得把被驱动表中的所有记录从磁盘上加载到内存中多少次。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">读磁盘代价太大,能<span style="color: black;">不可</span>在内存中操作呢?于是一个Join Buffer(连接缓冲区)的概念就<span style="color: black;">显现</span>了,Join Buffer<span style="color: black;">便是</span>执行连接<span style="color: black;">查找</span>前申请的<span style="color: black;">一起</span>固定<span style="color: black;">体积</span>的内存(默认256K),先把满足<span style="color: black;">要求</span>的若干条驱动表的记录装在这个Join Buffer中,<span style="color: black;">而后</span><span style="color: black;">起始</span>扫描被驱动表,每一条<strong style="color: blue;">「被驱动表」</strong>的记录一次性与Join Buffer中的所有记录进行匹配,<span style="color: black;">由于</span>匹配的过程都是在内存中完成的,<span style="color: black;">因此</span><span style="color: black;">这般</span><span style="color: black;">能够</span><span style="color: black;">明显</span>减少被驱动表的I/O代价。<span style="color: black;">运用</span>Join Buffer的过程如下图所示:</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「<span style="color: black;">为何</span>Join Buffer要装驱动表而不是被驱动表呢?上面说过,小表<span style="color: black;">做为</span>驱动表,Join Buffer装小表<span style="color: black;">更易</span>装得下,下一节会讲这个<span style="color: black;">原由</span>。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其实很好记忆,想想笛卡尔积<span style="color: black;">次序</span><span style="color: black;">亦</span>很<span style="color: black;">奥妙</span>。笛卡尔积的<span style="color: black;">次序</span><span style="color: black;">便是</span>一条被驱动表记录匹配多条驱动表记录的<span style="color: black;">次序</span>,而不是一条驱动表记录去匹配被驱动表的记录的<span style="color: black;">次序</span>,你<span style="color: black;">瞧瞧</span>这个<span style="color: black;">次序</span>是不是很神奇,<span style="color: black;">能够</span><span style="color: black;">自动</span>键两张表连接<span style="color: black;">瞧瞧</span>笛卡尔积,观察一下。</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">笛卡尔积<span style="color: black;">次序</span>是</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1 a 2 b</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2 b 2 b</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3 c 2 b</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">.....</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">而不是</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1 a 2 b</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1 a 3 c</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1 a 4 d</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">...</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">你<span style="color: black;">发掘</span>了吗?</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其实最好的<span style="color: black;">状况</span>是Join Buffer足够大,能容纳驱动表结果集中的所有记录,<span style="color: black;">这般</span>只<span style="color: black;">必须</span><span style="color: black;">拜访</span>一次被驱动表就<span style="color: black;">能够</span>完成连接操作了。这种加入了Join Buffer的嵌套循环连接算法<span style="color: black;">叫作</span>之为基于块的嵌套连接(Block Nested-Loop Join)算法。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这个Join Buffer的<span style="color: black;">体积</span>是<span style="color: black;">能够</span><span style="color: black;">经过</span><span style="color: black;">起步</span>参数<span style="color: black;">或</span>系统变量join_buffer_size进行配置,默认<span style="color: black;">体积</span>为262144字节(<span style="color: black;">亦</span><span style="color: black;">便是</span>256KB),最小<span style="color: black;">能够</span>设置为128字节。<span style="color: black;">针对</span>被驱动表,最好是为被驱动表加上效率高的索引,<span style="color: black;">倘若</span>实在<span style="color: black;">不可</span><span style="color: black;">运用</span>索引,<span style="color: black;">能够</span>尝试调大join_buffer_size的值来对连接<span style="color: black;">查找</span>进行优化。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">另一</span><span style="color: black;">必须</span><span style="color: black;">重视</span>的是,<span style="color: black;">仅有</span>满足<span style="color: black;">要求</span>的select中的列才会被放到Join Buffer中,<span style="color: black;">因此</span>再次提醒<span style="color: black;">咱们</span>,最好不要把*<span style="color: black;">做为</span><span style="color: black;">查找</span>列表,<span style="color: black;">这般</span>还<span style="color: black;">能够</span>在Join Buffer中<span style="color: black;">安置</span><span style="color: black;">更加多</span>的记录。</p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">4.Nested-Loop Join和Block Nested-Loop Join对比说明</span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">假设t1表的行数是N,t2表的行数是M,t1表是小表,即N < M</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「Simple Nested-Loop Join算法:」</strong></p>驱动表的每一条记录都会去被驱动表逐一匹配,<span style="color: black;">因此</span>总的扫描行数是N * M(开头说了,扫描表<span style="color: black;">便是</span>把表从磁盘加载到内存中);内存中的判断次数是N * M(扫描一次就会在内存中判断一次)。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">别纠结了,这种<span style="color: black;">办法</span>太笨了,不管<span style="color: black;">选取</span>哪个表<span style="color: black;">做为</span>驱动表,最后扫描和内存中判断的成本都是<span style="color: black;">同样</span>的。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「Index Nested-Loop Join算法」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">该算法被驱动表的<span style="color: black;">查找</span><span style="color: black;">要求</span>字段加上了合适的索引。</p>驱动表的每一条记录都会去被驱动表逐一匹配,<span style="color: black;">因此</span>总的扫描行数是N * log M(扫描行数不变,<span style="color: black;">然则</span><span style="color: black;">由于</span>被驱动表有索引,扫描速度会大大<span style="color: black;">增多</span>);内存中的判断次数是M * N(扫描一次就会在内存中判断一次)。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「Block Nested-Loop Join算法:」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">该算法又得区分Join Buffer装得下和装不下的<span style="color: black;">状况</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「Join Buffer装得下的<span style="color: black;">状况</span>」</strong></p>t1表和t2表都做一次全表扫描,将t1表记录都装入Join Buffer,总的扫描行数是M + N(开头说了,扫描表<span style="color: black;">便是</span>把表从磁盘加载到内存中,驱动表扫描M行一次性装到Join Buffer,被驱动表扫描一行会在Join Buffer进行比较,<span style="color: black;">最后</span>扫描N行);内存中的判断次数是M * N,<span style="color: black;">因为</span>Join Buffer是以<strong style="color: blue;">「无序数组」</strong>的方式组织的,<span style="color: black;">因此呢</span>对t2表中的每一行数据,都要与Join Buffer中的记录相比较。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到,调换这两个算式中的M和N没差别,<span style="color: black;">因此呢</span><span style="color: black;">此时</span>候<span style="color: black;">选取</span>t1还是t2表做驱动表,成本都是<span style="color: black;">同样</span>的。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「Join Buffer装不下的<span style="color: black;">状况</span>」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span>先用直观的数<span style="color: black;">据述</span>明过程,假如表t1是100行,而Join Buffer放不下,此时就分段放,执行过程就变<span style="color: black;">成为了</span>:</p>扫描表t1,<span style="color: black;">次序</span>读取数据行放入Join Buffer中,放完第80行Join Buffer满了,继续第2步;扫描表t2,把t2中的每一行取出来,跟Join Buffer中的所有记录做对比,满足join<span style="color: black;">要求</span>的,返回该条记录给MySQL客户端;清空Join Buffer;继续扫描表t1,<span style="color: black;">次序</span>读取最后的20行数据放入Join Buffer中,继续执行第2步。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这个流程<span style="color: black;">表现</span>出了这个算法名字中“Block”的由来,<span style="color: black;">暗示</span>“分块的join”。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">此刻</span>总结一下这个过程。驱动表t1的数据行数是N,假设<span style="color: black;">必须</span>分K次<span style="color: black;">才可</span>完成算法流程,被驱动表t2的数据行数是M。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>,<span style="color: black;">这儿</span>的K不是常数,N越大K就会越大。<span style="color: black;">因此</span>,在这个执行过程中:</p>扫描行数是N + K * M,每次装完一次Join Buffer,被驱动表t2的M条记录就会从头到尾去Join Buffer匹配,Join Buffer<span style="color: black;">必须</span>装K次,则扫描K次t2表;内存判断N * M次,<span style="color: black;">因为</span>Join Buffer是以<strong style="color: blue;">「无序数组」</strong>的方式组织的,<span style="color: black;">因此呢</span>对t2表中的每一行数据,都要与Join Buffer中的记录相比较。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">显然,内存判断次数是不受<span style="color: black;">选取</span>哪个表<span style="color: black;">做为</span>驱动表影响的。而扫描行数<span style="color: black;">思虑</span>到Join Buffer的<span style="color: black;">体积</span>,在M和N<span style="color: black;">体积</span>确定的<span style="color: black;">状况</span>下,驱动表的数据行数N小<span style="color: black;">有些</span>,则分段K就少<span style="color: black;">有些</span>,<span style="color: black;">那样</span><span style="color: black;">全部</span>表达式的结果会更小。</p><span style="color: black;">❝</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">总结:<span style="color: black;">倘若</span>Join Buffer能装任意一张表里的所有数据,<span style="color: black;">那样</span>不管<span style="color: black;">选取</span>哪个表<span style="color: black;">做为</span>驱动表,执行成本都<span style="color: black;">同样</span>。<span style="color: black;">针对</span>Join Buffer一次装不下驱动表的<span style="color: black;">状况</span>下,应该让小表当驱动表,<span style="color: black;">由于</span>小表记录总行数N越小,Join Buffer装完所需的次数K就越小,在N + K * M这个式子里,表达式的值越小。</p><span style="color: black;">❞</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">刚才</span><span style="color: black;">咱们</span>说了N越大,分段数K越大。<span style="color: black;">那样</span>N固定的时候,什么参数会影响K的<span style="color: black;">体积</span>呢?答案是join_buffer_size。join_buffer_size越大,Join Buffer中一次<span style="color: black;">能够</span>放入的行越多,分成的段数K<span style="color: black;">亦</span>就越少,对被驱动表的全表扫描次数就越少。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">join_buffer_size默认256K,我所在的<span style="color: black;">机构</span>配置的是4M。</p><span style="color: black;">❝</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1.<span style="color: black;">不可</span><span style="color: black;">运用</span>被驱动表的索引,只能<span style="color: black;">运用</span>Block Nested-Loop Join算法,<span style="color: black;">这般</span>的语句就<span style="color: black;">尽可能</span>不要<span style="color: black;">运用</span></p>2.Explain下,没用Index Nested-Loop 的全要优化<span style="color: black;">❞</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">「综上:从上面1234小节来看,无论哪种<span style="color: black;">状况</span>,总是应该<span style="color: black;">选取</span>小表<span style="color: black;">做为</span>驱动表。并且两张表有个各自的索引,<span style="color: black;">这般</span>表连接<span style="color: black;">才可</span>达到更好的性能。在内连接中,你<span style="color: black;">能够</span><span style="color: black;">运用</span>STRAIGHT_JOIN替换JOIN,<span style="color: black;">这般</span>在内连接中<span style="color: black;">便是</span>强制左表为驱动表。」</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">欢迎一键三连~</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"></p>
我深受你的启发,你的话语是我前进的动力。 你的见解独到,让我受益匪浅,非常感谢。 感谢楼主的分享!我学到了很多。
页:
[1]