对比了两个坏境的执行计划,代价预估及扫描算子、连接算子看起来都是一样的。
执行计划如下:
QUERY PLAN
Nested Loop Left Join (cost=8.58..1944.99 rows=1 width=866)
CTE s
-> Index Scan using emp_info_pkey on emp_info (cost=0.28..8.30 rows=1 width=57)
Index Cond: ((empno)::text = '200'::text)
Filter: (((emp_type)::text > '5'::text) AND ((emp_status)::text = 'Y'::text))
-> CTE Scan on s (cost=0.00..0.02 rows=1 width=256)
-> Index Scan using cust_info_pkey on cust_info a (cost=0.28..8.29 rows=1 width=200)
Index Cond: ((s.empno)::text = (cust_id)::text)
SubPlan 3
-> CTE Scan on r r_1 (cost=479.57..482.09 rows=1 width=118)
Filter: (((region_type)::text = '5'::text) AND ((region_status)::text = 'Y'::text))
CTE r
-> Recursive Union (cost=0.28..479.57 rows=101 width=19)
-> Index Scan using region_tbl_pkey on region_tbl f (cost=0.28..8.29 rows=1 width=19)
Index Cond: ((region_code)::text = (s.region_code)::text)
-> Hash Join (cost=0.33..46.93 rows=10 width=19)
Hash Cond: ((f_1.region_code)::text = (r.parent_region_code)::text)
-> Seq Scan on region_tbl f_1 (cost=0.00..39.00 rows=2000 width=19)
-> Hash (cost=0.20..0.20 rows=10 width=118)
-> WorkTable Scan on r (cost=0.00..0.20 rows=10 width=118)
SubPlan 5
-> CTE Scan on r r_3 (cost=479.57..482.09 rows=1 width=118)
Filter: (((region_type)::text = '4'::text) AND ((region_status)::text = 'Y'::text))
CTE r
-> Recursive Union (cost=0.28..479.57 rows=101 width=19)
-> Index Scan using region_tbl_pkey on region_tbl f_2 (cost=0.28..8.29 rows=1 width=19)
Index Cond: ((region_code)::text = (s.region_code)::text)
-> Hash Join (cost=0.33..46.93 rows=10 width=19)
Hash Cond: ((f_3.region_code)::text = (r_2.parent_region_code)::text)
-> Seq Scan on region_tbl f_3 (cost=0.00..39.00 rows=2000 width=19)
-> Hash (cost=0.20..0.20 rows=10 width=118)
-> WorkTable Scan on r r_2 (cost=0.00..0.20 rows=10 width=118)
SubPlan 7
-> CTE Scan on r r_5 (cost=479.57..482.09 rows=1 width=118)
Filter: (((region_type)::text = '3'::text) AND ((region_status)::text = 'Y'::text))
CTE r
-> Recursive Union (cost=0.28..479.57 rows=101 width=19)
-> Index Scan using region_tbl_pkey on region_tbl f_4 (cost=0.28..8.29 rows=1 width=19)
Index Cond: ((region_code)::text = (s.region_code)::text)
-> Hash Join (cost=0.33..46.93 rows=10 width=19)
Hash Cond: ((f_5.region_code)::text = (r_4.parent_region_code)::text)
-> Seq Scan on region_tbl f_5 (cost=0.00..39.00 rows=2000 width=19)
-> Hash (cost=0.20..0.20 rows=10 width=118)
-> WorkTable Scan on r r_4 (cost=0.00..0.20 rows=10 width=118)
SubPlan 9
-> CTE Scan on r r_7 (cost=479.57..482.09 rows=1 width=118)
Filter: (((region_type)::text = '2'::text) AND ((region_status)::text = 'Y'::text))
CTE r
-> Recursive Union (cost=0.28..479.57 rows=101 width=19)
-> Index Scan using region_tbl_pkey on region_tbl f_6 (cost=0.28..8.29 rows=1 width=19)
Index Cond: ((region_code)::text = (s.region_code)::text)
-> Hash Join (cost=0.33..46.93 rows=10 width=19)
Hash Cond: ((f_7.region_code)::text = (r_6.parent_region_code)::text)
-> Seq Scan on region_tbl f_7 (cost=0.00..39.00 rows=2000 width=19)
-> Hash (cost=0.20..0.20 rows=10 width=118)
-> WorkTable Scan on r r_6 (cost=0.00..0.20 rows=10 width=118)
(56 rows)
postgres=
从执行计划来看,代价预估中没有发现非常耗时的步骤。对正常的环境中explain analyze查看实际消耗,实际执行300ms,最终返回了一条数据,和代价预估基本一致。逐步排查,最终将重心放在了递归查询这部分。
递归部分sql:
with recursive r as (select f.ctid,f.region_code,f.parent_region_code,f.region_type,f.region_status
from region_tbl f where f.region_code=s.region_code union all select f.ctid, f.region_code,f.parent_region_code,
f.region_type,f.region_status from region_tbl f,r where f.region_code=r.parent_region_code)
分析sql逻辑,递归条件为f.region_code=r.parent_region_code,并且递归开始的f.region_code字段值为s.region_code=‘1200’,这里的1200是通过对s表进行查询得到的,如下: