对于表连接不可取的心态
- 因为影响性能而 完全弃用
- 不管三七二十一,不管什么复杂查询都用连接搞定。
连接的本质
方式: select * from project,repo;
结果:笛卡尔积(两个表的记录都取出来依次匹配并组合)
连接就是对笛卡尔积进行筛选。
- 连接查询中的过滤条件分类:单表条件、两表的条件
- 连接查询的执行步骤:
- 第一张表作为驱动表,驱动表的条件查询过滤获得结果
- 驱动表结果将两表条件转换为单表条件
- 查询被驱动表
- 注意执行逻辑:不是一次性取出所有驱动表结果,而是查出一条后就查询被驱动表一次。
驱动表只需要查询1此,而被驱动表需要查询多次数。
内连接外连接的起源:
学生姓名表与成绩表的关联查询中,有同学缺考无成绩,但是仍需要展示缺考学生的成绩。
普通的连接查询都是内连接,不会返回不匹配的结果。
左外连接和右外连接
选择将左表还是右表作为驱动表。
有时候匹配失败要加入结果集,有时候又不要,如何区分?
- where子句过滤:所有非匹配项都不加入结果集合
- on子句过滤:驱动表结果对应的被驱动表无匹配项目返回null。
为什么join查询中要有on子句?
处理场景:外连接驱动表中的记录在被驱动表中找不到匹配记录时是否要将被驱动表记录加入到结果集中。
如果对于没有匹配上的值,也应该显示我null而非不显示结果,应该使用join操作。
内连接中on和where等价。
格式: table1 left/right [outer] join table2
[可省略]
内连接的多种格式
from table1 , table2
from table1 join table2
from table1 inner join table2 [推荐]
from table1 cross join table2
连接的原理
最简单最笨拙的连接查询算法:
- 嵌套循环连接:三表连接也就是前两张表连接后的结果作为驱动表。
优化:
添加索引:被驱动表的查询条件列
基于块的嵌套循环连接(Block Nested-Loop Join):
如果被驱动表量大,会有很高的IO代码,需要尽量减少被驱动表的访问次数。
被驱动表记录加载到内存后,能否一次性与驱动表中的多条记录进行匹配?
Join Buffer:
装入多条/(最好是)所有 驱动表结果
Join Buffer Size: 通过系统变量join_buffer_size配置,默认256KB。
前往不能要*来查询数据,这样可以节省Buffer的空间。