我需要更新名为text
的表中名为table_to_update
的列。字段text
是来自另一个名为other_table
的表的3个字符串的串联。该脚本按预期工作,但问题是执行需要很长时间(> 20小时),因为表table_to_update
中有大约2000万个数据集需要更新。
有什么想法可以改善这个脚本的性能吗?
DECLARE
v_field1 VARCHAR(20);
v_field2 VARCHAR(20);
v_field3 VARCHAR(20);
v_text VARCHAR(100);
BEGIN
FOR rec IN (select t_pk from table_to_update where state = 'STATE_1' and text is null order by t_pk desc) -- 20 millions data sets
LOOP
v_text := null;
FOR other_record IN (select distinct field1, field1, field3 from other_table where t_fk = rec.t_pk)
LOOP
v_field1 := other_record.field1;
v_field2 := other_record.field2;
v_field3 := other_record.field3;
v_text := v_text || v_field2 || ';' || v_field1 || ': '|| v_field3 || ' ';
END LOOP;
update table_to_update set text = v_text where t_pk = rec.t_pk;
END LOOP;
COMMIT;
END;
答案 0 :(得分:2)
一般来说,优化PL / SQL块的最佳方法是最小化上下文切换的次数(即,从程序代码切换到SQL并返回的频率)。在这种情况下,您可以将此块减少为单个语句(假设您使用的是11g或更高版本):
MERGE INTO table_to_update t2u
USING (SELECT t_fk,
LISTAGG (field2 || ';' || field1 || ': ' || field3, ' ')
WITHIN GROUP (ORDER BY field2)
AS agg_field
FROM other_table
GROUP BY t_fk) ot
ON (ot.t_fk = t2u.t_pk)
WHEN MATCHED THEN
UPDATE SET
t2u.text = ot.agg_field
WHERE t2u.state = 'STATE_1' AND t2u.text IS NULL
LISTAGG
是一个聚合函数,用于连接获得的值
来自不同的行。它是在11g中引入的。UPDATE
执行此操作,但我更喜欢MERGE
。