sql - 我应该清除每个要在 forall 中使用的 fetch 循环的集合吗?PLSQL 甲骨文
问题描述
假设我在 table1 中有大量数据(100k-1m 行),我需要进行一些检查,然后根据过滤结果更新它们在 table2 上的状态。正如您在我的简化代码中看到的那样。我每批批量收集 1000 行并将它们过滤到 3 个不同的集合(dsa1、dsa2、dsa3)中,然后再将这 3 个集合更新到 table2 中。
我的问题是,假设第一次提取将 100 行放入 dsa1,然后第二次提取仅将 70 行放入 dsa1。当 forall 更新运行时,它还会从第一次提取更新 dsa1 中的旧 30 行。
2 我想到的解决方案是首先,删除收集每个 fetch 循环中的所有元素。第二个是将 forall 放在 fetch 循环之外,这将使 3 个集合非常大,但 forall 只调用一次。
第二种解决方案会占用大量内存吗?请咨询什么是最好的解决方案
declare
cursor c1 is
select t1.id, t1.status, t2.con from table1 t1, table2 t2
where t1.id = t2.id;
type ty_c1 is table of c1%rowtype;
asd1 ty_c1 := ty_c1();
type ty_id is table of c1.id%type index by pls_integer;
dsa1 ty_id;
dsa2 ty_id;
dsa3 ty_id;
begin
open c1;
loop
fetch c1 bulk collect into asd1 limit 1000;
exit when asd1.count = 0;
for i in 1 .. asd1.count
loop
if (asd1(i).status = 'ACT') then
dsa1(i).id := asd1(i).id;
elsif (asd1(i).status = 'NOT ACT') then
dsa2(i).id := asd1(i).id;
else
dsa3(i).id := asd1(i).id;
end if;
end loop;
forall idx in indices of dsa1
update table2 set con = 'ACTIVE'
where id = dsa1(idx).id;
forall idx in indices of dsa2
update table2 set con = 'NOT ACTIVE'
where id = dsa2(idx).id;
forall idx in indices of dsa3
update table2 set con = 'DEAD'
where id = dsa3(idx).id;
end loop;
close c1;
end;
解决方案
从性能的角度来看,构建三个集合并只访问一次数据库会提高性能,但会使用更多内存。
因此,答案取决于您将要处理的典型卷和可用内存。
您还可以有第四个集合,该集合保持为空,并将空集合分配给循环内的 dsa1、dsa2 和 dsa3,而不是删除条目。
但是看看你的代码,因为只有状态在改变,为什么不根据项目和状态的记录创建一个集合,或者有第二个集合来保存状态,然后不管状态如何,你将一次更新 1000 条记录一个集合。
更进一步,由于 1M 记录对于 Oracle 数据库来说不算什么,(数十亿记录是巨大的,一百万记录是微不足道的)只需使用数据库执行单个更新选择语句
update table2 t2
set conn=(select decode(t1.status, 'ACT', 'ACTIVE', 'NOT ACT','NON ACTIVE','DEAD')
from table1 t1)
where t2.id=t1.id
t2 中不存在于 t1 中的 NB 行将 conn 设置为 null,但如果不需要,您可以限制 where 子句以限制影响。
您还可以在更新和选择上添加并行提示以使用更多 CPU,如果您能够修改数据模型,使用数字代码而不是 varchar 来表示状态也会更有效。
推荐阅读
- tcl - 提高 tcl 的精度
- javascript - 从异步函数导入数据
- mongodb - 如何使用 Robo3T 连接作为 docker 容器运行的 mongodb 服务器
- visual-studio - VS2017 vstemplate自动安装Nuget包?
- html - 如何在悬停时向 SVG 内的路径元素添加阴影
- javascript - 每当套接字重新连接时,ChatClient websocket 都会多次绑定到事件
- reactjs - 为什么我能够有条件地以一种方式调用钩子,而不能以另一种方式调用?
- mysql - 我对 int 字段的 SQL 索引不起作用
- c# - 在winforms应用程序中将WebBrowser类升级为WebView类
- amazon-web-services - 安排 cloudwatch 并在两者之间停止安排