I wrote PostgreSQL function in which JSON array is parsed inside Loop. The Problem is it is taking too much time in case JSON Array size exceeds 1000 data. On top of that I used 2 IF statements inside loop. Is there some ways to make it faster.
My code
WHILE incr < json_size LOOP
jur_name2 := (SELECT my_json -> 'data' ->incr ->> 'JUR_NAME');
filial_code2 := (SELECT my_json -> 'data' ->incr ->> 'FILIAL_CODE');
activity_name2 := (SELECT my_json -> 'data' ->incr ->> 'ACTIVITY_NAME');
client_code2 := (SELECT my_json -> 'data' ->incr ->> 'CLIENT_CODE');
inn2 := (SELECT my_json -> 'data' ->incr ->> 'INN');
account2 := (SELECT my_json -> 'data' ->incr ->> 'ACCOUNT');
director_name2 := (SELECT my_json -> 'data' ->incr ->> 'DIRECTOR_NAME');
director_passport2 := (SELECT my_json -> 'data' ->incr ->> 'DIRECTOR_PASSPORT');
----------------------------------
phone_number2 := (SELECT my_json -> 'data' ->incr ->> 'PHONE_NUMBER');
reg_date2 := (SELECT my_json -> 'data' ->incr ->> 'REG_DATE');
owner_name2 := (SELECT my_json -> 'data' ->incr ->> 'OWNER_NAME');
accountant_name2 := (SELECT my_json -> 'data' ->incr ->> 'ACCOUNTANT_NAME');
terminal2 := (SELECT my_json -> 'data' ->incr ->> 'TERMINAL');
region_id2 := (SELECT my_json -> 'data' ->incr ->> 'REGION_ID');
credit_remainder := (SELECT my_json -> 'data' ->incr ->> 'CREDIT_REMAINDER');
credit_cnt := (SELECT my_json -> 'data' ->incr ->> 'CRED_CNT');
end_date := (SELECT CAST(my_json -> 'data' ->incr ->> 'END_DATE' AS DATE));
IF(NOT EXISTS(SELECT * FROM sp_clients WHERE client_code = client_code2)) THEN
INSERT INTO sp_clients(jur_name,filial_code,activity_name,client_code,inn,account,director_name,director_passport,phone_number,reg_date,owner_name,accountant_name,num_of_employees,plastic_cards,terminal,region_id,client_type)
VALUES(jur_name2,filial_code2,activity_name2,client_code2,inn2,account2,director_name2,director_passport2,phone_number2,reg_date2,owner_name2,accountant_name2,num_of_employees2,plastic_cards2,terminal2,region_id2,cl_type);
new_clients_incr := new_clients_incr + 1;
END IF;
INSERT INTO loan_portfolio(client_code,summa,cnt,oper_month)
SELECT client_code2,credit_remainder,credit_cnt,now()::date
WHERE
NOT EXISTS (
SELECT 1 FROM loan_portfolio WHERE oper_month = now()::date AND client_code = client_code2
);
incr := incr + 1;
END LOOP;
json
{
"data": [
{
"ACTIVITY_NAME": "Gardening",
"REGION_ID": 24,
"FILIAL_CODE": "00760",
"TERMINAL": 0,
"DIRECTOR_PASSPORT": "DD12453",
"INN": "233245",
"REG_DATE": "2020-07-01",
"END_DATE": "2020-06-30",
"CRED_CNT": 6,
"CREDIT_REMAINDER": 1.443828556508E10,
"ACCOUNT": "24546000200199297001",
"CLIENT_CODE": "65434234",
"JUR_NAME": "ggg",
"OWNER_NAME": "John Wick",
"DIRECTOR_NAME": "Iron Man",
"ACCOUNTANT_NAME": "Spider Man",
"PHONE_NUMBER": "000123321"
}
]
}
As you can see above code there bunch of attributes inside json array and looping through it taking much time. In addition I created index for columns that I check with If statements
inn2 := (SELECT my_json -> 'data' ->incr ->> 'INN');can be simplified toinn2 := my_json -> 'data' ->incr ->> 'INN';insert ... select...using e.g.jsonb_each()orjsonb_array_elements()in the SELECT statement.sp_clients.client_codeandloan_portfolio(oper_month, client_code)?sp_clients.client_codeis unique. Butloan_portfolio(oper_month, client_code)can be repeated as oper_month may vary for particularclient_code