10bet网址
MySQL 8.0参考手册
相关的文档10bet官方网站 本手册下载 本手册节选

8.2.1.10外连接简化

中的表表达式。查询的子句在许多情况下都被简化了。

在解析器阶段,具有右外连接操作的查询被转换为只包含左连接操作的等效查询。在一般情况下,转换是这样执行的:

(T1,…)右连接(t2,…)在P (T1,…, T2,…)

变成等价的左连接:

(T2,…)左连接(t1,…)在P (T1,…, T2,…)

窗体的所有内部连接表达式T1内连接t2上p (T1, t2)被列表取代了吗T1, T2P (T1, T2)连词的作为连接到的在哪里条件(或嵌入联接的联接条件,如果有的话)。

当优化器评估外部连接操作的计划时,它只考虑对于每个此类操作,在访问内部表之前访问外部表的计划。优化器的选择是有限的,因为只有这样的计划才能使用嵌套循环算法执行外部连接。

考虑这样一个表单的查询,其中R (T2)极大地减少表中匹配行的数量T2

Select * t1 left join t2 on p1 (t1, t2) where p (t1, t2) and r (t2)

如果按照写入的方式执行查询,优化器别无选择,只能访问受限制较少的表T1在更严格的表之前T2,这可能会产生一个非常低效的执行计划。

相反,MySQL将查询转换为没有外部连接操作的查询,如果在哪里条件是null-rejected。(也就是说,它将外部连接转换为内部连接。)如果外部连接操作的条件的计算结果为,则该条件被称为空拒绝未知的对于任何-补充的行生成的操作。

因此,对于这个外连接:

T1左连接t2上T1. a = t2 . a

诸如此类的条件被拒绝为null,因为它们对任何条件都不为真补充行(T2列设置为):

T2。B不是空t2。B > 3T2。C <= T1.C T2.B < 2 OR T2.C > 1

诸如此类的条件不会被null拒绝,因为它们可能对a为真补充行:

T2。B是零t1。B < 3或t2。B不是零t1。B < 3或t2。B > 3

检查外部连接操作的条件是否为空拒绝的一般规则很简单:

  • 这就是它的形式A不为空,在那里一个是任何内部表的属性

  • 它是一个谓词,包含对计算结果为的内部表的引用未知的当它的一个参数是

  • 它是一个连词,包含一个作为连词的空拒绝条件

  • 它是空拒绝条件的分离

对于查询中的一个外部连接操作,条件可以被空拒绝,而对于另一个外部连接操作,条件不能被空拒绝。在此查询中在哪里Condition在第二个外部连接操作中被拒绝为空,但在第一个外部连接操作中没有被拒绝为空:

Select * from t1 left join t2 . a = t1A左连接t3到t3, b = t1。B, t3, c, >, 0

如果在哪里条件为空拒绝查询中的外部连接操作,则外部连接操作将被内部连接操作替换。

例如,在前面的查询中,第二个外部连接被拒绝为空,可以用一个内部连接替换:

Select * from t1 left join t2 . a = t1t3上的一个内连接,b = t1。B, t3, c, >, 0

对于原始查询,优化器只计算与单个表访问顺序兼容的计划T1、T2、T3.对于重写的查询,它还会考虑访问顺序T3, T1, T2

一个外部连接操作的转换可能会触发另一个外部连接操作的转换。因此,查询:

Select * from t1 left join t2 . a = t1一个左连接t3到t3, b = t2。B, t3, c, >, 0

首先转换为查询:

Select * from t1 left join t2 . a = t1t3上的内连接t3, b = t2。B, t3, c, >, 0

这相当于查询:

Select * from (t1 left join t2 on t2 . a = t1 . a), t3 where t3 . c > 0 and t3 . b = t2 . b

其余的外部连接操作也可以由内部连接替换,因为条件T3.B = T2.Bnull-rejected。这将导致一个没有外部连接的查询:

Select * from (t1 inner join t2 on t2 . a = t1 . a), t3 where t3 . c > 0 and t3 . b = t2 . b

有时优化器可以成功地替换嵌入的外部连接操作,但不能转换嵌入的外部连接。以下查询:

Select * from t1 left join (t2 left join t3 on t3 . b = t2 . b) on t2 . a = t1A中t3。c > 0

转化为:

Select * from t1 left join (t2 inner join t3 on t3 . b = t2 . b) on t2 . a = t1A中t3。c > 0

只能重写为仍然包含嵌入外连接操作的形式:

Select * from t1 left join (t2, t3) on (t2 . a = t1)A和t3.b = t2.b

在查询中转换内嵌外连接操作的任何尝试都必须将内嵌外连接的连接条件与在哪里条件。在此查询中在哪里条件不是对嵌入外连接拒绝为空,而是对嵌入外连接的连接条件拒绝为空T2.A = T1。一个一个ND T3.C=T1.Cnull-rejected:

Select * from t1 left join (t2 left join t3 on t3 . b = t2 . b) on t2 . a = t1A和t3。c = t1。c,其中t3。D > 0或者t1。D > 0

因此,查询可以转换为:

Select * from t1 left join (t2, t3) on t2 . a = t1A和t3.c = t1.c和t3.b = t2。B在T3。D > 0OR T1.D > 0