1

I have the following function which is taking around 6secs time to complete the execution on 25,000 records.

Function:

CREATE OR REPLACE FUNCTION public.fun_getData
( 
    p_pin VARCHAR(15), 
    p_datetime TIMESTAMP 
)
RETURNS NUMERIC(5,1)
AS
$BODY$
DECLARE v_pfcode        VARCHAR(20);
DECLARE v_starttime     TIMESTAMP;
DECLARE v_endtime       TIMESTAMP;
DECLARE v_num           NUMERIC(5,2);
DECLARE v_gpdata        NUMERIC(5,2);
DECLARE v_timedata      NUMERIC(5,2);
DECLARE v_sales         VARCHAR(10);

BEGIN

    SELECT col_sale INTO v_sales FROM public.tbl_Sales WHERE sales_id ='A01';

    IF v_sales = '-'
    THEN
        RETURN 0;
    END IF;

    SELECT pfcode, gpdata INTO v_pfcode,v_gpdata
    FROM public.tbl_fdata 
    WHERE fpin=p_pin;

    v_gpdata := COALESCE(v_gpdata,0);

    IF v_pfcode IS NULL
    THEN
        RETURN v_gpdata;
    END IF;

    SELECT StartTime, EndTime, num INTO v_starttime,v_endtime,v_num
    FROM public.salesyears
    WHERE s_pfcode =v_pfcode AND y.year = date_part('year',p_datetime);

    IF v_starttime IS NULL OR v_endtime IS NULL
    THEN 
        RETURN v_gpdata;
    END IF;

    IF v_starttime < v_endtime
    THEN
        IF p_datetime >= v_starttime AND p_datetime < v_endtime THEN 
          v_timedata :=  v_gpdata + v_num;
        ELSE 
            v_timedata := v_gpdata;
        END IF;
    ELSE 
    IF p_datetime >= v_endtime AND p_datetime < v_starttime THEN
        v_timedata := v_gpdata;
    ELSE  
        v_timedata := v_gpdata + v_num;
    END IF;
    END IF;
                
    RETURN v_timedata;
    END;
$BODY$
LANGUAGE plpgsql;

Function Call:

select 120*public.fun_getData(col_pin, modifieddate) 
from public.tbl_prddata
where code = 'XMOP';

Taking around 00:00:06 time to execute.

Note: Same function I have created in SQL Server environment on same data set, it gets executed with second.

Execution Plan: explain(analyze,verbose,buffers)

"Seq Scan on public.tbl_prddata  (cost=0.00..8141.61 rows=23647 width=32) (actual time=0.253..5970.663 rows=25011 loops=1)"
"  Output: ('120'::numeric * public.fun_getData((col_pin)::character varying, (modifieddate)::timestamp without time zone))"
"  Filter: ((tbl_prddata.code)::sys.""varchar"" = 'XMOP'::sys.""varchar"")"
"  Rows Removed by Filter: 86508"
"  Buffers: shared hit=116845"
"Query Identifier: 5592079453045444499"
"Planning Time: 0.076 ms"
"Execution Time: 5980.916 ms"

Edit: Added more execution plan's:

Query 1:

EXPLAIN(ANALYZE, VERBOSE, BUFFERS)
SELECT col_sale FROM public.tbl_Sales WHERE sales_id ='A01';

--Output:

"Index Scan using idx_tbl_Sales_colob on public.tbl_Sales  (cost=0.14..8.16 rows=1 width=7) (actual time=0.250..0.251 rows=1 loops=1)"
"  Output: col_sale"
"  Index Cond: ((tbl_Sales.sales_id)::sys.""varchar"" = 'A01'::sys.""varchar"")"
"  Buffers: shared hit=9"
"Query Identifier: 6306884246769163476"
"Planning:"
"  Buffers: shared hit=50"
"Planning Time: 0.183 ms"
"Execution Time: 0.266 ms"

Query 2:

EXPLAIN(ANALYZE, VERBOSE, BUFFERS)
SELECT pfcode, gpdata FROM public.tbl_fdata WHERE fpin='PRD01';

--Output:

"Index Scan using idx_tbl_fdata_colx on public.tbl_fdata  (cost=0.12..8.14 rows=1 width=46) (actual time=0.027..0.027 rows=1 loops=1)"
"  Output: pfcode, gpdata"
"  Index Cond: ((tbl_fdata.fpin)::sys.""varchar"" = 'PRD01'::sys.""varchar"")"
"  Buffers: shared hit=2"
"Query Identifier: -4137289472330654813"
"Planning:"
"  Buffers: shared hit=655"
"Planning Time: 1.415 ms"
"Execution Time: 0.047 ms"

Query 3:

EXPLAIN(ANALYZE, VERBOSE, BUFFERS)
SELECT StartTime, EndTime, num 
FROM public.salesyears
WHERE s_pfcode ='all' AND year = date_part('year','2023-01-01 00:20:00');

--Output:

"Seq Scan on public.salesyears y  (cost=0.00..1.47 rows=1 width=30) (actual time=0.064..0.064 rows=0 loops=1)"
"  Output: StartTime, EndTime, num"
"  Filter: (((s_pfcode)::sys.""varchar"" = 'all'::sys.""varchar"") AND ((year)::double precision = '2023'::double precision))"
"  Rows Removed by Filter: 27"
"  Buffers: shared hit=1"
"Query Identifier: 7071532767670856741"
"Planning:"
"  Buffers: shared hit=56"
"Planning Time: 0.280 ms"
"Execution Time: 0.074 ms"

Query 4:

explain(analyze,verbose,buffers)
select * from public.tbl_prddata
where code= 'XMOP';

--Output:

"Seq Scan on public.tbl_prddata  (cost=0.00..2372.74 rows=22847 width=263) (actual time=0.075..104.757 rows=23031 loops=1)"
"  Output: cola,colb,colc,cold,cole,colf,colg,colh"
"  Filter: ((tbl_prddata.code)::sys.""varchar"" = 'XMOP'::sys.""varchar"")"
"  Rows Removed by Filter: 31588"
"  Buffers: shared hit=1690"
"Query Identifier: 7714647889345744025"
"Planning Time: 0.093 ms"
"Execution Time: 106.360 ms"
MAK
  • 6,824
  • 25
  • 74
  • 131
  • Not performance related, but: `declare` starts a _block_ to declare one or multiple variables. There is no need to start a new block for each variable. –  Jan 04 '23 at 10:26
  • @a_horse_with_no_name, Even after removing that, performance remains same. – MAK Jan 04 '23 at 10:29
  • Your function contains three different select statements on three tables, could you share the results from EXPLAIN(ANALYZE, VERBOSE, BUFFERS) for these three statements? – Frank Heikens Jan 04 '23 at 11:05
  • And could you also share the results from a call without the function? Just: select * from public.tbl_prddata where code = 'XMOP'; – Frank Heikens Jan 04 '23 at 11:07
  • @FrankHeikens, Added more execution plans. – MAK Jan 04 '23 at 11:29
  • 2
    rows=25011, that how many times you call the function fun_getData(). It has to be super super fast to get below 1 second, or you need a different strategy to get the data. I would drop the function and just JOIN the tables to get the results needed. – Frank Heikens Jan 04 '23 at 11:39

0 Answers0