数据库版本:oracle12c
前面一直说的都是单表查询的情况,没有考虑多表查询的情况,然而正常的业务系统一般会有一半以上都是多表查询,所以玩转单表查询并不完全满足我们的需求,而对多表查询多一些认识,也将给我们带来更多的sql语句参考因数。
再说到数据库多表查询之前,可以先看一哈在数学概念上将表定义成一个集合,而表链接则是在做集合运算,多表查询也算是一种集合运算,至于更深入的如何做运算,最好就不要太追究了,因为很明显我也不会。我们只需要有这么一个印象,就是表示一个集合,里面每行数据是一个元素。有这样一个简化的对象,我们在后面才好说它表现出的动作,以及动作背后的一些原理。
表连接-无连接:
笛卡尔集应该听说过,他会形成一个N x M的大表,然后可以再在里面做选择,映射。(选择filter过滤条件,需要输出的结果选择)。
表链接-嵌套循环连接nested-loop
这个是有连接条件的情况,就是两张表有连接关系,所以可以依靠连接关系从一张表的数据去找另外一张表,这个过程就像是先选出驱动表的所有符合条件的元素,再根据这个元素,轮流按照连接关系去找非驱动表的它的对象,每一个驱动元素他在驱动结果集是一个一个去,到了非驱动表如果没有索引他仍然是一个一个的挨到起看,是不是符合要求,直到找完所有非驱动表的对象(table access full)这是一个全表读,知道最后一个找完才返回结果集,所以他需要大概需要1次驱动表全表扫描+n(驱动表结果集元素个数)次非驱动表全表扫描。这并不好,是吧?因为一张表重复读多次,是不是有问题?所以就有了后面的其他连接
表连接-hash连接
如果的如果,他没有一次一次的想要去那边一次一次的挨着去寻找,或许他可以尝试直接走到对方面前。这就是hash连接,hash连接如其名,就是hash运算,他会首先读出多张表的数据,进行hash运算,比较hash值,这是一个高效的过程,但是却是一个耗内存的过程,如果表越大,效果倒不是很好。
表连接-排序连接
为了解决以上的问题,又提出了一个新的连接方式,如果我们两边都排个顺序,我只需要找到我要的那个值的附近就可以了,不用读多少次,也不用遍历多少次数据,只需要排个序就解决一切。当然一切美丽的东西只是因为他刚好符合美的标准,当你转过身就发现,他对大表的性能简直就是垃圾,而且不管你要查多少数据,他都要排序,一个大表,没事儿就排序,没事就排序,我只查一条数据也给我排序,是不是除了排序它什么都不会了。那确实如此,所以排序连接在oracle应用场景是最少的。
表连接-优化建议
针对嵌套循环连接,或许你发现了一个问题,我们会首先查驱动表的数据,如果给驱动表查询条件加索引,那么我们就能很快得到驱动结果集,如果再在非驱动表的连接条件上加索引,那么我们就很快查到非驱动表的数据并通过它的过滤条件排除数据,最后得到查询结果集,这是一个索引传递的过程,我们没有在驱动表连接字段上加索引,我们也没在非驱动表过滤条件加索引,但它通过驱动表的过滤条件索引传递到了非驱动表的过滤条件,这是一个可以被利用的特性。
针对hash连接,建议就是我们的表每一行的大小不要太大了,如果太大了,实际上oracle自身不会走hash连接
关于排序连接,如果在两边查询结果都比较大,占到百分之50以上的时候,oracle就有可能走排序连接,当然我们也可以考虑,索引本身就是有序的特点,通过非空索引列做连接,这样就可以省略掉排序过程。 总的来说,这种情况出现的比较少。
网友评论