如何优化这个 PL/SQL 块?
How to optimize this PL/SQL block?
我需要在名为 table_to_update
的 table 中更新名为 text
的列。字段 text
是来自另一个名为 other_table
的 table 的 3 个字符串的串联。该脚本按预期工作,但问题是执行时间很长(> 20 小时),因为 table 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;
一般来说,优化 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
。
我需要在名为 table_to_update
的 table 中更新名为 text
的列。字段 text
是来自另一个名为 other_table
的 table 的 3 个字符串的串联。该脚本按预期工作,但问题是执行时间很长(> 20 小时),因为 table 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;
一般来说,优化 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
。