I have a table that contains information about the different tables in my database. For each table in it, I want regular logging (daily) to be done. The problem is that I have done this using for loop, and it is taking a lot of time to execute in Redshift. I am giving the queries I used to create my table, logging table and the Procedure that uses the for loop. Please suggest an alternate method to implement this without for loop. Structure of table that contains info of different tables:
CREATE TABLE public.info_schema_table
(
info_schema_name character varying(200) ENCODE lzo,
info_object_name character varying(200) ENCODE lzo,
info_object_type character varying(200) ENCODE lzo,
info_object_full_name character varying(400) ENCODE lzo
)
DISTSTYLE EVEN;
Here, object name refers to the table name, object_type contains if the table is view or table, and the object_full_name stores the concatenated name of the table with the schema i.e. if schema name is "test_schema" then full name is "test_schema.table_name". Structure of table in which logging needs to be stored:
CREATE TABLE public.redshift_logging_table
(
log_schema_name character varying(30) ENCODE lzo,
log_object_name character varying(30) ENCODE lzo,
log_object_type character varying(30) ENCODE lzo,
log_refresh_date date ENCODE az64,
log_refresh_count bigint ENCODE az64,
log_total_count bigint ENCODE az64
)
DISTSTYLE EVEN;
Here, refresh_date stores the date of logging, refresh_count stores the number of records inserted in the table on that particular day and total_count contains the total number of records in the table till the logging date.
Just for clarification, here's one sample record of the info_schema_table:
Here's my procedure that I am using to fill the logging table:
CREATE OR REPLACE PROCEDURE public.REDSHIFT_LOGGING_PROCEDURE()
AS $$
DECLARE
var_total_count bigint;
var_records_today bigint;
my_row record;
my_cursor CURSOR
FOR select info_schema_name, info_object_name, info_object_type , info_object_full_name from INFO_SCHEMA_TABLE ;
BEGIN
open my_cursor;
LOOP
FETCH my_cursor INTO my_row;
EXIT WHEN NOT FOUND;
BEGIN
EXECUTE ' select count(1)::bigint from '||my_row.INFO_OBJECT_FULL_NAME INTO var_total_count;
var_records_today=var_total_count-(select log_total_count from REDSHIFT_LOGGING_TABLE where REFRESH_DATE=current_date-1 and LOG_OBJECT_NAME=my_row.INFO_OBJECT_NAME);
insert into REDSHIFT_LOGGING_TABLE
(LOG_SCHEMA_NAME,LOG_OBJECT_NAME,LOG_OBJECT_TYPE,LOG_REFRESH_DATE, LOG_REFRESH_COUNT, LOG_TOTAL_COUNT )
values
(my_row.info_schema_name, my_row.info_object_name, my_row.info_object_type , current_date, var_records_today, var_total_count);
END;
END LOOP;
END;
$$ LANGUAGE plpgsql
SECURITY INVOKER;
All the table only increase in number of records day by day, so records inserted on any particular day is always >=0.
Issue is that, this procedure works but only for small records in info_schema_table, if I run it for around 1000 records, the procedure doesn't completes on Redshift even in one hour.
PLEASE suggest an alternate method to execute it without using for loop. Thank you.
