查看“外连接简化”的源代码
←
外连接简化
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
在许多情况下,查询中FROM子句中的表达式会被简化。 在解析阶段,具有右外连接操作的查询会被转换为只包含左连接操作的等价查询。一般情况下,转换如下: (T1, ...) RIGHT JOIN (T2, ...) ON P(T1, ..., T2, ...) 转换为等价的左连接: (T2, ...) LEFT JOIN (T1, ...) ON P(T1, ..., T2, ...) 所有形式为 T1 INNER JOIN T2 ON P(T1, T2) 的内连接表达式将被替换为 T1, T2 的列表,并作为连词与 WHERE 条件(或嵌套连接的连接条件,如果有的话)连接在一起。 当优化器评估外连接操作的计划时,它只考虑那些在每个外连接操作中,外部表在内部表之前访问的计划。优化器的选择是受限的,因为只有这种计划才能使用嵌套循环算法执行外连接。 考虑以下形式的查询,其中 R(T2) 大大减少了与表T2匹配的行数: SELECT * T1 FROM T1 LEFT JOIN T2 ON P1(T1,T2) WHERE P(T1,T2) AND R(T2) 如果按照原样执行查询,优化器只能访问限制较少的表T1,然后才能访问限制较多的表T2,这可能会产生非常低效的执行计划。 相反,如果WHERE条件被拒绝为null(即,将外连接转换为内连接),MySQL会将查询转换为不包含外连接操作的查询。对于外连接操作,如果条件在为该操作生成的任何NULL补充行上评估为FALSE或UNKNOWN,那么该条件被称为被null拒绝。 因此,对于以下外连接: T1 LEFT JOIN T2 ON T1.A=T2.A 像这样的条件会被null拒绝,因为它们在任何NULL补充行(T2列设置为NULL)上都不可能为真: T2.B IS NOT NULL T2.B > 3 T2.C <= T1.C T2.B < 2 OR T2.C > 1 而像这样的条件不会被null拒绝,因为它们可能对NULL补充行成立: T2.B IS NULL T1.B < 3 OR T2.B IS NOT NULL T1.B < 3 OR T2.B > 3 对于检查条件是否被null拒绝进行外连接操作的一般规则很简单: *条件的形式为 A IS NOT NULL,其中 A 是任一内部表的属性 *条件是一个谓词,包含对内部表的引用,当其参数为NULL时,评估结果为UNKNOWN *条件是一个包含null被拒绝条件的合取式 *条件是多个null被拒绝条件的析取式 在查询中,一个条件可能对某个外连接操作被null拒绝,而对另一个外连接操作则不被null拒绝。在以下查询中,WHERE条件对第二个外连接操作被null拒绝,但对第一个外连接操作则不被null拒绝: SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A LEFT JOIN T3 ON T3.B=T1.B WHERE T3.C > 0 如果在查询中,WHERE条件对外连接操作被null拒绝,那么该外连接操作会被替换为内连接操作。 例如,在上述查询中,第二个外连接被null拒绝,可以被替换为内连接: SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A INNER JOIN T3 ON T3.B=T1.B WHERE T3.C > 0 对于原始查询,优化器只评估与单个表访问顺序T1、T2、T3兼容的计划。对于重写后的查询,它还会考虑访问顺序T3、T1、T2。 一个外连接操作的转换可能会触发另一个外连接操作的转换。因此,查询: SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A LEFT JOIN T3 ON T3.B=T2.B WHERE T3.C > 0 首先被转换为: SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A INNER JOIN T3 ON T3.B=T2.B WHERE 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.B被null拒绝。这导致查询中没有任何外连接: 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=T1.A WHERE T3.C > 0 被转换为: SELECT * FROM T1 LEFT JOIN (T2 INNER JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A WHERE T3.C > 0 这只能被重写为仍包含嵌套外连接操作的形式: SELECT * FROM T1 LEFT JOIN (T2,T3) ON (T2.A=T1.A AND T3.B=T2.B) WHERE T3.C > 0 在尝试转换查询中的嵌套外连接操作时,必须考虑嵌套外连接的连接条件以及WHERE条件。在这个查询中,WHERE条件对于嵌套外连接来说不是被null拒绝的,但是embedding外连接的连接条件T2.A=T1.A AND T3.C=T1.C是被null拒绝的: SELECT * FROM T1 LEFT JOIN (T2 LEFT JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A AND T3.C=T1.C WHERE T3.D > 0 OR T1.D > 0 因此,查询可以被转换为: SELECT * FROM T1 LEFT JOIN (T2, T3) ON T2.A=T1.A AND T3.C=T1.C AND T3.B=T2.B WHERE T3.D > 0 OR T1.D > 0
返回至“
外连接简化
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
查看
阅读
查看源代码
查看历史
更多
搜索
导航
首页
基础知识
正则表达式
Markdown
分布式
项目管理
系统集成项目管理基础知识
云原生
Docker
云原生安全
云原生词汇表
十二因素应用
Kubernetes
音频处理
音频合成
Edge-tts
CMS系统
Docsify
VuePress
Mediawiki
自动生成
Marp
CI/CD
GitLab
设计
颜色
平面设计
AI
数字人
操作系统
GNU/Linux
数据库
Mysql
工具
链入页面
相关更改
特殊页面
页面信息