子查询返回多列可以使用join的方式,但有些需求join效率不如在子查询中返回多列那么好.具体使用子查询中返回多列还是join请根据需求和执行计划决定. 快速阅读请从第3节开始.
创建"xxxxxx集团公司",在"xxxxxx集团公司"下创建100个部门,部门名称在数据1514736000-1546272000之间随机生成.
insert into departments(parentid,name) values(0,'xxxxxx集团公司'); insert into departments(parentid,name) select 1 as parentid, (random()*(1546272000-1514736000)+1514736000)::bigint as name from generate_series(1,999);创建100万部门人员,随机分布在各个部门,人员名称在数据1514736000-1546272000之间随机生成.同时每个部门的最高领导只有1人.
do $$ declare v_start bigint; v_end bigint; begin for i in 1..1000 loop v_start := (i-1)*1000 + 1; v_end := v_start + 999; insert into deppeoples(depid,name,title,tel,sex,national) select (random()*(100-1)+1)::integer as depid, (random()*(1546272000-1514736000)+1514736000)::bigint as name, (random()*(9-1)+1)::integer as title, (random()*(13999999999-13000000000)+13000000000)::bigint as tel, (random()*(3-1)+1)::integer as sex, (random()*(54-1)+1)::integer as national from generate_series(v_start,v_end); raise notice '%,%', v_start,v_end; end loop; end; $$;为保证测试的准确性,生成完成后运行vacuum.
vacuum freeze verbose analyze departments; vacuum freeze verbose analyze deppeoples;执行5次,取最后一次,可以看到left join共扫描了3012页,用时3.296 ms
QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=0.42..7796.00 rows=1 width=38) (actual time=3.257..3.257 rows=0 loops=1) Output: t1.name, t2.name, t2.title, t2.tel Buffers: shared hit=3012 -> Seq Scan on public.departments t1 (cost=0.00..21.00 rows=1000 width=15) (actual time=0.009..0.200 rows=1000 loops=1) Output: t1.objectid, t1.parentid, t1.name, t1.describe, t1.generate, t1.state Buffers: shared hit=11 -> Index Scan using idx_deppeoples_depid on public.deppeoples t2 (cost=0.42..7.76 rows=1 width=31) (actual time=0.003..0.003 rows=0 loops=1000) Output: t2.objectid, t2.depid, t2.name, t2.title, t2.tel, t2.sex, t2."national", t2.mail, t2.describe, t2.generate, t2.state Index Cond: ((t2.depid = t1.objectid) AND (t2.title = 10)) Buffers: shared hit=3001 Planning Time: 0.314 ms Execution Time: 3.296 ms (12 rows)执行5次,取最后一次,可以看到子查询共扫描了3012页,用时8.827 ms
QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- CTE Scan on cte (cost=8481.00..8501.00 rows=1000 width=100) (actual time=0.042..8.584 rows=1000 loops=1) Output: cte.department, (cte.r).name1, (cte.r).title1, (cte.r).tel1 Buffers: shared hit=3012 CTE cte -> Seq Scan on public.departments t1 (cost=0.00..8481.00 rows=1000 width=43) (actual time=0.036..7.363 rows=1000 loops=1) Output: t1.name, (SubPlan 1) Buffers: shared hit=3012 SubPlan 1 -> Limit (cost=8.46..8.46 rows=1 width=40) (actual time=0.006..0.006 rows=0 loops=1000) Output: (ROW(t2.name, t2.title, t2.tel)::deppeoples01), t2.objectid Buffers: shared hit=3001 -> Sort (cost=8.46..8.46 rows=1 width=40) (actual time=0.005..0.005 rows=0 loops=1000) Output: (ROW(t2.name, t2.title, t2.tel)::deppeoples01), t2.objectid Sort Key: t2.objectid DESC Sort Method: quicksort Memory: 25kB Buffers: shared hit=3001 -> Index Scan using idx_deppeoples_depid on public.deppeoples t2 (cost=0.42..8.45 rows=1 width=40) (actual time=0.003..0.003 rows=0 loops=1000) Output: ROW(t2.name, t2.title, t2.tel)::deppeoples01, t2.objectid Index Cond: ((t2.depid = t1.objectid) AND (t2.title = 10)) Buffers: shared hit=3001 Planning Time: 0.237 ms Execution Time: 8.827 ms (22 rows)