MYSQL Nested Join Optimization
table_factor的语法和标准sql比较,后者只接受table_reference,每个逗号项都等于一个inner Join,e.g.
SELECT * FROM t1 LEFT JOIN (t2, t3, t4)
ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
等于:
SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)
ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
在mysql中,cross join 语法上等效与 inner join(他们可以互相替换),在标准sql中,他们并不等效,
一般情况下,在只包含inner join操作的join表达式中,圆括号可以被忽略,但外连接时,省略圆括号会带来不一样的结果:
t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b=t3.b OR t2.b IS NULL)
ON t1.a=t2.a
转变:
(t1 LEFT JOIN t2 ON t1.a=t2.a) LEFT JOIN t3
ON t2.b=t3.b OR t2.b IS NULL
然而,这两个表达式并不等效,假设:
1: 表t1包含 行(1),(2);
2: 表t2包含行(1,101);
3: 表t3包含行(101); 在这种情况下,第一个表达式返回的结果集包括(1,1,101,101) ,(2,null,null,null),然而第二表达式返回(1,1,101,101),(2,null,null,101);
mysql> select * from
-> t1 left join
-> (t2 left join t3 on t2.b = t3.b or t2.b is null )
-> on t1.a = t2.a;
+------+------+------+------+
| a | a | b | b |
+------+------+------+------+
| 1 | 1 | 101 | 101 |
| 2 | NULL | NULL | NULL |
+------+------+------+------+
2 rows in set (0.02 sec) mysql> select * from
-> (t1 left join t2 on t1.a = t2.a)
-> left join t3
-> on t2.b = t3.b or t2.b is null;
+------+------+------+------+
| a | a | b | b |
+------+------+------+------+
| 1 | 1 | 101 | 101 |
| 2 | NULL | NULL | 101 |
+------+------+------+------+
2 rows in set (0.00 sec)
<============================================================================>
t1 LEFT JOIN (t2, t3) ON t1.a=t2.a
该表达式不能转变成:
t1 LEFT JOIN t2 ON t1.a=t2.a, t3.
Database changed
mysql> select * from t1 left join (t2,t3) on t1.a = t2.a;
+------+------+------+------+
| a | a | b | b |
+------+------+------+------+
| 1 | 1 | 101 | 101 |
| 2 | NULL | NULL | NULL |
+------+------+------+------+
2 rows in set (0.00 sec) mysql> select * from t1 left join t2 on t1.a = t2.a, t3;
+------+------+------+------+
| a | a | b | b |
+------+------+------+------+
| 1 | 1 | 101 | 101 |
| 2 | NULL | NULL | 101 |
+------+------+------+------+
2 rows in set (0.00 sec)
不同的结果集
因此,如果我们去掉有outer join操作的join表达式的圆括号,我们会改变原始表达式的结果集。
更加准确的,我们不能去掉左外连接的右括号操作,和右外连接的左括号操作。换句话,我们不能去掉外连接操作中的内表表达式的括号,外表的其他操作括号可以被去掉;
(t1,t2) LEFT JOIN t3 ON P(t2.b,t3.b)
等效于:
t1, t2 LEFT JOIN t3 ON P(t2.b,t3.b)
SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b=t3.b) ON t1.a=t2.a
WHERE t1.a > 1 SELECT * FROM t1 LEFT JOIN (t2, t3) ON t1.a=t2.a
WHERE (t2.b=t3.b OR t2.b IS NULL) AND t1.a > 1
这梁查询都包含内连接:
t2 LEFT JOIN t3 ON t2.b=t3.b
t2, t3
SELECT * FROM T1 INNER JOIN T2 ON P1(T1,T2)
INNER JOIN T3 ON P2(T2,T3)
WHERE P(T1,T2,T3).
该表达式的执行顺序:
FOR each row t1 in T1 {
FOR each row t2 in T2 such that P1(t1,t2) {
FOR each row t3 in T3 such that P2(t2,t3) {
IF P(t1,t2,t3) {
t:=t1||t2||t3; OUTPUT t;
}
}
}
}
SELECT * FROM T1 LEFT JOIN
(T2 LEFT JOIN T3 ON P2(T2,T3))
ON P1(T1,T2)
WHERE P(T1,T2,T3).
顺序:
FOR each row t1 in T1 {
BOOL f1:=FALSE;
FOR each row t2 in T2 such that P1(t1,t2) {
BOOL f2:=FALSE;
FOR each row t3 in T3 such that P2(t2,t3) {
IF P(t1,t2,t3) {
t:=t1||t2||t3; OUTPUT t;
}
f2=TRUE;
f1=TRUE;
}
IF (!f2) {
IF P(t1,t2,NULL) {
t:=t1||t2||NULL; OUTPUT t;
}
f1=TRUE;
}
}
IF (!f1) {
IF P(t1,NULL,NULL) {
t:=t1||NULL||NULL; OUTPUT t;
}
}
}
在一般情况下,对于在一外联接操作的任何嵌套循环的第一内表,一个标志被引入在循环之前处于关闭并在循环之后被检查。该标志被打开时,用于从外部表的当前行从代表内操作数表中找到一个匹配的。如果在循环周期结束的标志仍然关闭,没有发现匹配的外部表的当前行。在这种情况下,该行被用于内表的列补充NULL值。结果行被传递到最后的检查为输出或到下一个嵌套循环,但仅当行满足所有嵌入式外的连接条件。
对于外连接的查询,优化器可以只选择为循环表外循环在内部表之前的顺序。因此,我们外部连接的查询,只有一个嵌套顺序是可能的。对于下面的查询,优化器将评估两个不同的嵌套:
SELECT * T1 LEFT JOIN (T2,T3) ON P1(T1,T2) AND P2(T1,T3)
WHERE P(T1,T2,T3)
FOR each row t1 in T1 {
BOOL f1:=FALSE;
FOR each row t2 in T2 such that P1(t1,t2) {
FOR each row t3 in T3 such that P2(t1,t3) {
IF P(t1,t2,t3) {
t:=t1||t2||t3; OUTPUT t;
}
f1:=TRUE
}
}
IF (!f1) {
IF P(t1,NULL,NULL) {
t:=t1||NULL||NULL; OUTPUT t;
}
}
}
和:
FOR each row t1 in T1 {
BOOL f1:=FALSE;
FOR each row t3 in T3 such that P2(t1,t3) {
FOR each row t2 in T2 such that P1(t1,t2) {
IF P(t1,t2,t3) {
t:=t1||t2||t3; OUTPUT t;
}
f1:=TRUE
}
}
IF (!f1) {
IF P(t1,NULL,NULL) {
t:=t1||NULL||NULL; OUTPUT t;
}
}
}
如果P可以拆分:
P(T1,T2,T2) = C1(T1) AND C2(T2) AND C3(T3).
算法会变成
FOR each row t1 in T1 such that C1(t1) {
FOR each row t2 in T2 such that P1(t1,t2) AND C2(t2) {
FOR each row t3 in T3 such that P2(t2,t3) AND C3(t3) {
IF P(t1,t2,t3) {
t:=t1||t2||t3; OUTPUT t;
}
}
}
}
每个合取C1(T1)的,C 2(T2),C 3(T3)被压出的最内环到最外循环在那里可以进行评估。如果C1(T 1)是一个非常严格的条件下,此条件下推可能大大从传递给内表T1减少行数。其结果是,在执行时间的查询可能提高极大。
MYSQL Nested Join Optimization的更多相关文章
- MySQL的JOIN(三):JOIN优化实践之内循环的次数
这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( i ...
- MySQL的JOIN(四):JOIN优化实践之快速匹配
这篇博文讲述如何优化扫描速度.我们通过MySQL的JOIN(二):JOIN原理得知了两张表的JOIN操作就是不断从驱动表中取出记录,然后查找出被驱动表中与之匹配的记录并连接.这个过程的实质就是查询操作 ...
- MySQL 的 join 功能弱爆了?
大家好,我是历小冰,今天我们来学习和吐槽一下 MySQL 的 Join 功能. 关于MySQL 的 join,大家一定了解过很多它的"轶事趣闻",比如两表 join 要小表驱动大表 ...
- [HIve - LanguageManual] Join Optimization (不懂)
Join Optimization Join Optimization Improvements to the Hive Optimizer Star Join Optimization Star S ...
- MySQL Left Join,Right Join
魂屁,东西发这里了关于Left Join,Right Join的 在讲MySQL的Join语法前还是先回顾一下联结的语法,呵呵,其实连我自己都忘得差不多了,那就大家一起温习吧(如果内容有错误或有疑问, ...
- MySQL Full Join的实现
MySQL Full Join的实现 由于MySQL不支持FULL JOIN,以下是替代方法 left join + union(可去除反复数据)+ right join select * from ...
- mysql left join
MySQL左连接不同于简单连接.MySQL LEFT JOIN提供该表额外字段在左侧. 如果使用LEFT JOIN,得到的所有记录的匹配方式相同, 在左边表中得到的每个记录不匹配也会有一个额外的记录. ...
- MySQL的JOIN(一):用法
JOIN的含义就如英文单词"join"一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. CREATE TABLE ...
- MySQL的JOIN(五):JOIN优化实践之排序
这篇博文讲述如何优化JOIN查询带有排序的情况.大致分为对连接属性排序和对非连接属性排序两种情况.插入测试数据. CREATE TABLE t1 ( id INT PRIMARY KEY AUTO_I ...
随机推荐
- 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数
问题描述: 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数. 算法一: 对数组a[n]进行冒泡排序,如果冒泡所得的最值和前一个最值相等,则该最值为重复的数. 分析: 该算法时间复杂 ...
- Selectize使用总结
一.简介 Selectize是一个可扩展的基于jQuery 的自定义下拉框的UI控件.它对展示标签.联系人列表.国家选择器等比较有用.它的大小在~ 7kb(gzip压缩)左右.提供一个可靠且体验良好的 ...
- Spring MVC报错:The request sent by the client was syntactically incorrect ()
原因: 1.参数名称不一致 2.参数类型不一致
- 快速开发基于 HTML5 网络拓扑图应用--入门篇(一)
计算机网络的拓扑结构是引用拓扑学中研究与大小,形状无关的点.线关系的方法.把网络中的计算机和通信设备抽象为一个点,把传输介质抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构.网络的拓扑结构 ...
- BASIC-3 字母图形 循环 字符串
基础练习 字母图形 时间限制:1.0s 内存限制:256.0MB 问题描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCD ...
- [Spark内核] 第35课:打通 Spark 系统运行内幕机制循环流程
本课主题 打通 Spark 系统运行内幕机制循环流程 引言 通过 DAGScheduelr 面向整个 Job,然后划分成不同的 Stage,Stage 是從后往前划分的,执行的时候是從前往后执行的,每 ...
- fastdfs集群
高可用的两大目的:数据备份,数据分片 1.FastDFS安装配置 先配置一台,将其中的配置文件打包,下载,然后配置其他机器时只需要解压即可, 打包命令 然后下载,上传到其他机器相对应的/etc目录下 ...
- 自学Aruba之路
自学Aruba之路[第一回]:体系结构 1.1 自学Aruba1.1-Aruba体系结构-产品线 1.2 自学Aruba1.2-WLAN一些基本常识 1.3 自学Aruba1.3-W ...
- PHP curl请求https遇到的坑
PHP里curl对https的证书配置默认是服务器端要求验证的,如果服务器端没有配置证书验证,则无法请求https路径.如果为了简便使用不需要配置https证书的话,配置curl时将以下两项设置为fa ...
- Lua和C的语法差别
没有main函数 Lua是脚本语言,没有固定入口的main函数.当lua解析器解析某个lua代码文件时,lua解析器一样一行的解析lua脚本. print("Hello lua") ...