mysql left join分析
2014-03-14 14:01
197 查看
mysql> desc product1;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | 0 | |
| amount | int(10) unsigned | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> desc product_details;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | NULL | |
| weight | int(10) unsigned | YES | | NULL | |
| exist | int(10) unsigned | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from product1;
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
| 4 | 400 |
| 5 | 100 |
| 6 | 200 |
| 7 | 300 |
| 8 | 400 |
| 9 | 100 |
| 10 | 200 |
| 11 | 300 |
| 12 | 400 |
| 13 | 100 |
| 14 | 200 |
| 15 | 300 |
| 16 | 400 |
| 17 | 100 |
| 18 | 200 |
| 19 | 300 |
+----+--------+
19 rows in set (0.00 sec)
mysql> select * from product_details;
+----+--------+-------+
| id | weight | exist |
+----+--------+-------+
| 2 | 22 | 0 |
| 4 | 44 | 1 |
| 5 | 55 | 0 |
| 6 | 66 | 1 |
| 23 | 25 | 30 |
+----+--------+-------+
5 rows in set (0.00 sec)
mysql> select * from product1 left join product_details on product1.id=product_details.id;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
| 4 | 400 | 4 | 44 | 1 |
| 5 | 100 | 5 | 55 | 0 |
| 6 | 200 | 6 | 66 | 1 |
| 1 | 100 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 7 | 300 | NULL | NULL | NULL |
| 8 | 400 | NULL | NULL | NULL |
| 9 | 100 | NULL | NULL | NULL |
| 10 | 200 | NULL | NULL | NULL |
| 11 | 300 | NULL | NULL | NULL |
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
19 rows in set (0.00 sec)
left join原理:
查看执行计划,驱动表为product1 ,首先全表扫描product1,得到product1的记录19条,然后全表扫描product_details,得到product_details的记录5条,然后再join buffer缓存里面join连接,取product1第一条;id=1那条与product_details的5条逐一比较,如果和5条都不相等,则将product1整条输出+product_details(所有列为NULL填充),如果相等则显示将product1整条+匹配的product_details行,依次循环。
mysql> select * from product1 left join product_details on product1.id=product_details.id and product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
| 5 | 100 | NULL | NULL | NULL |
| 6 | 200 | NULL | NULL | NULL |
| 7 | 300 | NULL | NULL | NULL |
| 8 | 400 | NULL | NULL | NULL |
| 9 | 100 | NULL | NULL | NULL |
| 10 | 200 | NULL | NULL | NULL |
| 11 | 300 | NULL | NULL | NULL |
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
19 rows in set (0.01 sec)
这个是在上面那条语句的基础上,判断下除了判断product1.id是否等于product_details。id外,还要判断product1.id是否等于11,等于的话,就输出product1的行+product_details的行,否则输出product1的行+product_details(NULL替换的行)
mysql> select * from product1 left join product_details on product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | 2 | 22 | 0 |
| 11 | 300 | 4 | 44 | 1 |
| 11 | 300 | 5 | 55 | 0 |
| 11 | 300 | 6 | 66 | 1 |
| 11 | 300 | 23 | 25 | 30 |
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
| 5 | 100 | NULL | NULL | NULL |
| 6 | 200 | NULL | NULL | NULL |
| 7 | 300 | NULL | NULL | NULL |
| 8 | 400 | NULL | NULL | NULL |
| 9 | 100 | NULL | NULL | NULL |
| 10 | 200 | NULL | NULL | NULL |
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
23 rows in set (0.00 sec)
这条语句的执行计划是:全表扫描product1得到19行,全表扫描product_details得到5行,放入 join buffer中join。取product1第一条,在product_details的5行逐条连接,看是否product1.id=11,是的话输出改行数据,不是的话就输出product1.id行数据+product_details(NULL数据),依次循环。
mysql> select * from product1 left join product_details on product1.id=11 where product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | 2 | 22 | 0 |
| 11 | 300 | 4 | 44 | 1 |
| 11 | 300 | 5 | 55 | 0 |
| 11 | 300 | 6 | 66 | 1 |
| 11 | 300 | 23 | 25 | 30 |
+----+--------+------+--------+-------+
5 rows in set (0.00 sec)
这条语句执行计划解读:
mysql> create table t01 as select * from product1 where product1.id=11;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from t01 left join product_details on t01.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | 2 | 22 | 0 |
| 11 | 300 | 4 | 44 | 1 |
| 11 | 300 | 5 | 55 | 0 |
| 11 | 300 | 6 | 66 | 1 |
| 11 | 300 | 23 | 25 | 30 |
+----+--------+------+--------+-------+
5 rows in set (0.00 sec)
从product1的索引 in_01中扫描获得product1.id=11所在的数据块,然后获取product1 where product1.id=11的行数据,该行数据再与product_details关联5次,并核实是否product1.id=11,是的话,输出product1行数据+product_details行数据,不相等就不输出product1行数据+product_details行(NULL)数据。而不是一些人所说的 where是对join
结果集的过滤。
mysql> select * from product1 left join product_details on product_details.id=6 where product1.id in(6,7);
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 6 | 200 | 6 | 66 | 1 |
| 7 | 300 | 6 | 66 | 1 |
+----+--------+------+--------+-------+
2 rows in set (0.00 sec)
mysql> select * from product1 left join product_details on product_details.id=11 where product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
1 row in set (0.00 sec)
mysql> select * from product1 left join product_details on product_details.id=11 where product1.id>11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
8 rows in set (0.00 sec)
上几条sql 都是一样的原理
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | 0 | |
| amount | int(10) unsigned | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> desc product_details;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | NULL | |
| weight | int(10) unsigned | YES | | NULL | |
| exist | int(10) unsigned | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from product1;
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
| 4 | 400 |
| 5 | 100 |
| 6 | 200 |
| 7 | 300 |
| 8 | 400 |
| 9 | 100 |
| 10 | 200 |
| 11 | 300 |
| 12 | 400 |
| 13 | 100 |
| 14 | 200 |
| 15 | 300 |
| 16 | 400 |
| 17 | 100 |
| 18 | 200 |
| 19 | 300 |
+----+--------+
19 rows in set (0.00 sec)
mysql> select * from product_details;
+----+--------+-------+
| id | weight | exist |
+----+--------+-------+
| 2 | 22 | 0 |
| 4 | 44 | 1 |
| 5 | 55 | 0 |
| 6 | 66 | 1 |
| 23 | 25 | 30 |
+----+--------+-------+
5 rows in set (0.00 sec)
mysql> select * from product1 left join product_details on product1.id=product_details.id;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
| 4 | 400 | 4 | 44 | 1 |
| 5 | 100 | 5 | 55 | 0 |
| 6 | 200 | 6 | 66 | 1 |
| 1 | 100 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 7 | 300 | NULL | NULL | NULL |
| 8 | 400 | NULL | NULL | NULL |
| 9 | 100 | NULL | NULL | NULL |
| 10 | 200 | NULL | NULL | NULL |
| 11 | 300 | NULL | NULL | NULL |
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
19 rows in set (0.00 sec)
left join原理:
查看执行计划,驱动表为product1 ,首先全表扫描product1,得到product1的记录19条,然后全表扫描product_details,得到product_details的记录5条,然后再join buffer缓存里面join连接,取product1第一条;id=1那条与product_details的5条逐一比较,如果和5条都不相等,则将product1整条输出+product_details(所有列为NULL填充),如果相等则显示将product1整条+匹配的product_details行,依次循环。
mysql> select * from product1 left join product_details on product1.id=product_details.id and product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
| 5 | 100 | NULL | NULL | NULL |
| 6 | 200 | NULL | NULL | NULL |
| 7 | 300 | NULL | NULL | NULL |
| 8 | 400 | NULL | NULL | NULL |
| 9 | 100 | NULL | NULL | NULL |
| 10 | 200 | NULL | NULL | NULL |
| 11 | 300 | NULL | NULL | NULL |
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
19 rows in set (0.01 sec)
这个是在上面那条语句的基础上,判断下除了判断product1.id是否等于product_details。id外,还要判断product1.id是否等于11,等于的话,就输出product1的行+product_details的行,否则输出product1的行+product_details(NULL替换的行)
mysql> select * from product1 left join product_details on product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | 2 | 22 | 0 |
| 11 | 300 | 4 | 44 | 1 |
| 11 | 300 | 5 | 55 | 0 |
| 11 | 300 | 6 | 66 | 1 |
| 11 | 300 | 23 | 25 | 30 |
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
| 5 | 100 | NULL | NULL | NULL |
| 6 | 200 | NULL | NULL | NULL |
| 7 | 300 | NULL | NULL | NULL |
| 8 | 400 | NULL | NULL | NULL |
| 9 | 100 | NULL | NULL | NULL |
| 10 | 200 | NULL | NULL | NULL |
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
23 rows in set (0.00 sec)
这条语句的执行计划是:全表扫描product1得到19行,全表扫描product_details得到5行,放入 join buffer中join。取product1第一条,在product_details的5行逐条连接,看是否product1.id=11,是的话输出改行数据,不是的话就输出product1.id行数据+product_details(NULL数据),依次循环。
mysql> select * from product1 left join product_details on product1.id=11 where product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | 2 | 22 | 0 |
| 11 | 300 | 4 | 44 | 1 |
| 11 | 300 | 5 | 55 | 0 |
| 11 | 300 | 6 | 66 | 1 |
| 11 | 300 | 23 | 25 | 30 |
+----+--------+------+--------+-------+
5 rows in set (0.00 sec)
这条语句执行计划解读:
mysql> create table t01 as select * from product1 where product1.id=11;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from t01 left join product_details on t01.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | 2 | 22 | 0 |
| 11 | 300 | 4 | 44 | 1 |
| 11 | 300 | 5 | 55 | 0 |
| 11 | 300 | 6 | 66 | 1 |
| 11 | 300 | 23 | 25 | 30 |
+----+--------+------+--------+-------+
5 rows in set (0.00 sec)
从product1的索引 in_01中扫描获得product1.id=11所在的数据块,然后获取product1 where product1.id=11的行数据,该行数据再与product_details关联5次,并核实是否product1.id=11,是的话,输出product1行数据+product_details行数据,不相等就不输出product1行数据+product_details行(NULL)数据。而不是一些人所说的 where是对join
结果集的过滤。
mysql> select * from product1 left join product_details on product_details.id=6 where product1.id in(6,7);
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 6 | 200 | 6 | 66 | 1 |
| 7 | 300 | 6 | 66 | 1 |
+----+--------+------+--------+-------+
2 rows in set (0.00 sec)
mysql> select * from product1 left join product_details on product_details.id=11 where product1.id=11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 11 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
1 row in set (0.00 sec)
mysql> select * from product1 left join product_details on product_details.id=11 where product1.id>11;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 12 | 400 | NULL | NULL | NULL |
| 13 | 100 | NULL | NULL | NULL |
| 14 | 200 | NULL | NULL | NULL |
| 15 | 300 | NULL | NULL | NULL |
| 16 | 400 | NULL | NULL | NULL |
| 17 | 100 | NULL | NULL | NULL |
| 18 | 200 | NULL | NULL | NULL |
| 19 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
8 rows in set (0.00 sec)
上几条sql 都是一样的原理
相关文章推荐
- 系统分析书籍推荐
- 谈“库存管理”分析设计中的两个重点
- 基于Tuscany的Web应用程序分析
- 一个蓝屏记录文件(DMP)分析
- 字符、字符数组、char、string的区别分析
- ELF可执行格式文件实例分析
- 虚拟化动手实验之高可用实现:需求分析(三)
- sk_buffer 详细分析
- 游标脚本性能问题解决与分析 (2) - Cursor Performance Analysis
- memcached 源代码阅读笔记(4)- SET 操作分析
- Android中View绘制流程以及invalidate()等相关方法分析
- Handler的源码分析
- Oracle数据库的安全策略分析(三)
- mysql中char与varchar的区别分析
- varnish pipe 和pass的区别分析
- 用代码和UML图化解设计模式之桥接模式的深入分析
- 使用AsyncTask异步更新UI界面及原理分析
- 关于掉落的详细分析。
- 如何让网站分析报告更有价值?
- 性能分析工具firebug.console.profile(title)