본문 바로가기

PostgreSQL

PostgreSQL 비 결정적 변수에 대한 실행 계획

변수 v_id 값이 공백인 경우와 공백이 아닌 경우에 따라 실행 계획이 달라져야 하는데
SQL Server 의 경우 실행 계획 재 사용을 위해 2가지 상태의 실행 계획을 동시에 가지고 있는다
두 가지 모두 가지고 있는다는 의미는 변수 값이 공백이 아니면 or 절 이후 쿼리는 필요 없으나 실행 계획에 포함되어 있어
조회를 하게 된다.
그러나 PG 의 경우 실행계획을 재활용 하지 않기 때문에 결정된 변수의 값에 따라 플랜을 만들므로
SQL Server 와 같은 성능 이슈는 발생하지 않는다.
CREATE OR REPLACE FUNCTION get_test1m 
( 
	v_id character varying, 
	v_system_id character varying 
) 
RETURNS TABLE  
( 
	id integer,  
	system_id	varchar(100), 
	svc_name	varchar(100) 
) 
LANGUAGE 'plpgsql' 
AS $$ 
BEGIN 
    RETURN QUERY  
	SELECT a.id, a.system_id, a.svc_name FROM test1m as a  
	JOIN public.test2m AS B ON A.system_id = B.system_id 
		where  
		(v_system_id = '' or a.system_id > v_system_id) 
		and (v_id = '' or a.id <> any(select * from  unnest(string_to_array(v_id,',')::int[])) ) 
	order by a.system_id 
	limit 10000; 
END; $$
2022-12-20 12:56:31.874 KST [11268] 濡œ洹?  duration: 361.982 ms  plan:
Query Text: SELECT a.id, a.system_id, a.svc_name FROM test1m as a
JOIN public.test2m AS B ON A.system_id = B.system_id
where
(v_system_id = '' or a.system_id > v_system_id)
and (v_id = '' or a.id <> any(select * from  unnest(string_to_array(v_id,',')::int[])) )
order by a.system_id
limit 10000
Limit  (cost=0.85..3307.92 rows=10000 width=43) (actual time=304.485..360.012 rows=10000 loops=1)
  ->  Merge Join  (cost=0.85..187671.77 rows=567484 width=43) (actual time=304.484..359.505 rows=10000 loops=1)
        Merge Cond: ((a.system_id)::text = (b.system_id)::text)
        ->  Index Scan using ix_system_id on test1m a  (cost=0.42..132966.05 rows=300453 width=43) (actual time=0.051..43.584 rows=10315 loops=1)
              Index Cond: ((system_id)::text > 'b'::text)
        ->  Index Only Scan using ix2_system_id on test2m b  (cost=0.42..45780.42 rows=999733 width=6) (actual time=0.019..121.634 rows=702250 loops=1)
              Heap Fetches: 0