假设master_table包含许多记录,并且master_table,tableA,tableB,tableC和tableD的“id”字段在商业意义上都是相同的。
对于下面显示的2个选择语句,
他们都会返回相同的结果集吗?
哪一个会有更好的表现?
我认为如果tableA_tmp,tableB_tmp,tableC_tmp和tableD_tmp都返回较小的结果集,SQL1将比SQL2快,因为oracle不需要为每个master_table记录查询tableA_tmp,tableB_tmp,tableC_tmp和tableD_tmp一次。
但是如果tableA_tmp,tableB_tmp,tableC_tmp和tableD_tmp都返回大的结果集,SQL 2将会快得多,因为加入许多大结果集的成本远远高于查询tableA_tmp,tableB_tmp,tableC_tmp和tableD_tmp一次每个master_table记录。
如果我有任何误解,请纠正我。或建议的任何其他方法?
SQL1:
select
master_table.* ,
tableA_tmp.cnt as tableA_cnt ,
tableB_tmp.cnt as tableB_cnt ,
tableC_tmp.cnt as tableC_cnt ,
tableD_tmp.cnt as tableD_cnt
from
master_table,
(select tableA.id as id, count(1) as cnt from tableA group by tableA.id) tableA_tmp,
(select tableB.id as id, count(1) as cnt from tableB group by tableB.id) tableB_tmp,
(select tableC.id as id, count(1) as cnt from tableC group by tableC.id) tableC_tmp,
(select tableD.id as id, count(1) as cnt from tableD group by tableD.id) tableD_tmp
where
master_table.id = tableA_tmp.id(+) and
master_table.id = tableB_tmp.id(+) and
master_table.id = tableC_tmp.id(+) and
master_table.id = tableD_tmp.id(+) ;
SQL 2:
select
master_table.* ,
(select count(*) from tableA where tableA.id = master_table.id) as tableA_cnt,
(select count(*) from tableB where tableB.id = master_table.id) as tableB_cnt,
(select count(*) from tableC where tableC.id = master_table.id) as tableC_cnt,
(select count(*) from tableD where tableD.id = master_table.id) as tableD_cnt
from
master_table;
答案 0 :(得分:3)
查看执行计划
答案 1 :(得分:3)
连接通常比内联查询更好 - 对从主查询返回的每一行执行内联查询。
这意味着(1)优于(2)。至少在99%的情况下。
在少数情况下,定义数据和方式索引的分布可以在将查询执行时间倾向于2更高效时发挥作用,但这在普通数据库中很少发生。
答案 2 :(得分:1)
在较短的时间内开展工作的人。
答案 3 :(得分:0)
不同的结果集。 考虑TableA是否为空。
在语句1中,tableA_tmp也是空的。使用外连接时,将返回一行,但tableA_tmp.cnt的值将为null。
在语句2中,计数将被执行并返回零值。
两者的性能可能更好或更差,具体取决于卷,索引,scalar subquery caching,表聚类因子,内存....
答案 4 :(得分:0)
如果Master表和其他表足够大,SQL 1会更快。原因是表扫描。表扫描很昂贵,因为扫描涉及I / O.第一个查询只需要对表tableA,tableB,tablec和tableD中的每个表进行单次扫描。
在SQL2中,对于主表中的每个键,将对表tableA,tableB,tablec和tableD进行特殊扫描。如果主表有10行,表tableA将被扫描10次,tableB将被扫描10次,tableC将被扫描10次,依此类推。成本会很高。
示例将说明这一点。假设每个表都有1000条记录,每条记录都有不同的id。在第一个查询中,表tableA,tableB,tablec和tableD将被扫描一次,结果将被连接。生成的行数很大,但会在合理的时间内过滤。在SQL2中,每个表tableA,tableB,tablec和tableD将被扫描1000次。这是非常昂贵的。