Concat bigint Array Values in a Function - Mailing list pgsql-general

From Vinay Gupta
Subject Concat bigint Array Values in a Function
Date
Msg-id CAEzDN6xVUn5VP6rP+U2ZVrcw-39uME0dLLJjZDTEyfzRzdG++Q@mail.gmail.com
Whole thread Raw
Responses Re: Concat bigint Array Values in a Function  (David G Johnston <david.g.johnston@gmail.com>)
List pgsql-general
Hi,

I need to optimise and aggregate array integer values in a function and i am doing this by below stored function :

-- type def
CREATE TYPE fun_type AS (
        g_id integer,
        zip_id_list integer[],
        city_id_list integer[],
        state_id_list integer[],
        lat_long_id_list bigint[],
        country_id_list bigint[],
        ccid_list bigint[],
        cr_id_list bigint[],
        is_active boolean
);

-- fun def

CREATE OR REPLACE FUNCTION fun_multicountry()
  RETURNS SETOF fun_type AS
$BODY$
DECLARE
    row1 fun_type%ROWTYPE;
    dt1 record;
    dt1outer record;
BEGIN
    FOR dt1outer IN SELECT DISTINCT g_id FROM tableA
    LOOP
        row1.country_id_list = '{}';
        row1.state_id_list = '{}';
        row1.city_id_list = '{}';
        row1.lat_long_id_list = '{}';
        row1.zip_id_list = '{}';
        row1.ccid_list = '{}';
        row1.cr_id_list = '{}';
        row1.g_id = dt1outer.g_id;
        row1.is_active = false;
        FOR dt1 IN SELECT * FROM tableA LEFT OUTER JOIN tableB
            ON (pr_id =  tableB.id) where 
            g_id = dt1outer.g_id AND tableA.is_active = true 
            
        LOOP
            row1.is_active = true;
            IF(dt1.geot_type_id =1 and dt1.pr_id is not NULL)
            THEN 
                row1.cr_id_list = row1.cr_id_list|| dt1.targeting_ids;
            ELSIF(    (dt1.state_id_list is null or dt1.state_id_list = '{}') AND
                (dt1.city_id_list is null or dt1.city_id_list = '{}') AND
                (dt1.lat_long_id_list is null or dt1.lat_long_id_list = '{}') AND
                (dt1.zip_id_list is null or dt1.zip_id_list = '{}'))
            THEN
                row1.country_id_list = row1.country_id_list || dt1.country_id;
            ELSE
                row1.state_id_list = row1.state_id_list || dt1.state_id_list;
                row1.city_id_list = row1.city_id_list || dt1.city_id_list;
                row1.lat_long_id_list = row1.lat_long_id_list || dt1.lat_long_id_list;
                row1.zip_id_list = row1.zip_id_list || dt1.zip_id_list;    
            END IF;    
            IF(dt1.ccid_list is null or dt1.ccid_list = '{}')    
                    THEN
                         row1.ccid_list = row1.ccid_list || -dt1.country_id;
            ELSE
                row1.ccid_list = row1.ccid_list || dt1.ccid_list;
            END IF;    
        END LOOP;
        return NEXT row1;
    END LOOP;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;

Above function is taking ~ 30 -40 sec to finish where as table rows are :

explain analyze select fun_multicountry();

                                             QUERY PLAN                                             

----------------------------------------------------------------------------------------------------

 Result  (cost=0.00..5.25 rows=1000 width=0) (actual time=21855.881..21959.683 rows=420286 loops=1)

 Total runtime: 31977.712 ms

(2 rows)


Time: 21978.103 ms

select count(*) from tableA;

 count  

--------

 629439

(1 row)


Time: 135.858 ms

select count(*) from tableB;

 count 

-------

   841

select count(distinct g_id) from tableA;

 count  

--------

 420287


I need to aggregate all different array values in table depending upon above if conditions and return them. Is dere any optimal approach to do this as i am calling this function in many other functions and its just adding to slowness. I am trying to rewrite using CASE statements. Will this help ?

Please let me know if there is any optimal way to finish this function in ~ 2-3 secs

Thanks

pgsql-general by date:

Previous
From: Keith Fiske
Date:
Subject: Updating timezone setting
Next
From: Robin Ranjit Singh Chauhan
Date:
Subject: repmgr