如何 运行 批处理模式下的存储过程或 运行 并行处理中的存储过程
how to run the stored procedure in batch mode or in run it in parallel processing
我们正在迭代来自全局临时 table.below 的 100k+ 条记录,存储过程将逐条迭代来自全局临时 table 的所有记录,并且必须处理以下三个步骤。
- 查看产品是否存在
- 查看资产中的产品是否有'category'。
- 查看资产的文件名是否以“%pdf%”开头。
所以每条记录都要经过这3个步骤,最终的文件名会被存储在table中,才算成功记录。如果任何步骤中出现任何错误,则会为该记录存储错误消息。
以下存储过程需要很长时间才能处理,因为它是按顺序处理的。
- 有没有办法通过批处理使存储过程本身的这个过程更快?
- 如果在存储过程中不可行,那么我们可以将这段代码改为Java和运行多线程模式下的这段代码吗?比如创建 10 个线程,每个线程将同时获取一条记录并处理这段代码。如果有人提供一些伪代码,我会很高兴。
建议使用哪种方法?
DECLARE
V_NODE_ID VARCHAR2(20);
V_FILENAME VARCHAR2(100);
V_CATEGORY_COUNT INTEGER :=0;
FINAL_FILNAME VARCHAR2(2000);
V_FINAL_ERRORMESSAGE VARCHAR2(2000);
CURSOR C1 IS
SELECT isbn FROM GT_ADD_ISBNS GT;
CURSOR C2(v_isbn in varchar2) IS
SELECT ANP.NODE_ID NODE_ID
FROM
table1 ANP,
table2 ANPP,
table3 AN
WHERE
ANP.NODE_ID=AN.ID AND
ANPP.NODE_ID=ANP.NODE_ID AND
AN.NAME_ID =26 AND
ANP.CATEORGY='category' AND
ANP.QNAME_ID='categories' AND
ANP.NODE_ID IN(SELECT CHILD_NODE_ID
FROM TABLE_ASSOC START WITH PARENT_NODE_ID IN(v_isbn)
CONNECT BY PRIOR CHILD_NODE_ID = PARENT_NODE_ID);
BEGIN
--Iterating all Products
FOR R1 IN C1
LOOP
FINAL_FILNAME :='';
BEGIN
--To check whether Product is exists or not
SELECT AN.ID INTO V_NODE_ID
FROM TABLE1 AN,
TABLE2 ANP
WHERE
AN.ID=ANP.NODE_ID AND
ANP.VALUE in(R1.ISBN);
V_CATEGORY_COUNT :=0;
V_FINAL_ERRORMESSAGE :='';
--To check Whether Product inside the assets are having the 'category' is applied or not
FOR R2 IN C2(R1.ISBN)
LOOP
V_CATEGORY_COUNT := V_CATEGORY_COUNT+1;
BEGIN
--In this Logic Product inside the assets have applied the 'category' But those assets are having documents LIKE '%pdf%' or not
SELECT ANP.STRING_VALUE into V_FILENAME
FROM
table1 ANP,
table2 ANPP,
table3 ACD
WHERE
ANP.QNAME_ID=21 AND
ACD.ID=ANPP.LONG_VALUE
ANP.NODE_ID=ANPP.NODE_ID AND
ANPP.QNAME_ID=36 AND
ANP.STRING_VALUE LIKE '%pdf%' AND
ANP.NODE_ID=R2.NODE_ID;
FINAL_FILNAME := FINAL_FILNAME || V_FILENAME ||',';
EXCEPTION WHEN
NO_DATA_FOUND THEN
V_FINAL_ERRORMESSAGE:=V_FINAL_ERRORMESSAGE|| 'Category is applied for this Product But for the asset:'|| R2.NODE_ID || ':Documents[LIKE %pdf%] were not found ;';
UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE= V_FINAL_ERRORMESSAGE WHERE ISBN= R1.ISBN;
END;--Iterating for each NODEID
END LOOP;--Iterating the assets[Nodes] for each product of catgeory
-- DBMS_OUTPUT.PUT_LINE('R1.ISBN:' || R1.ISBN ||'::V_CATEGORY_COUNT:' || V_CATEGORY_COUNT);
IF(V_CATEGORY_COUNT = 0) THEN
UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE= 'Category is not applied to none of the Assets for this Product' WHERE ISBN= R1.ISBN;
END IF;
EXCEPTION WHEN
NO_DATA_FOUND THEN
UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE= 'Product is not Found:' WHERE ISBN= R1.ISBN;
END;
-- DBMS_OUTPUT.PUT_LINE( R1.ISBN || 'Final documents:'||FINAL_FILNAME);
UPDATE GT_ADD_ISBNS SET FILENAME=FINAL_FILNAME WHERE ISBN= R1.ISBN;
COMMIT;
END LOOP;--looping gt_isbns
END;
您有许多潜在的性能问题。这是一个:
"We are iterating 100k+ records from global temporary table"
全局临时 tables 可能会很慢。填充它们意味着将所有数据写入磁盘;从他们那里读取意味着从磁盘读取。很多 I/O 可能是可以避免的。此外,GTT 使用 临时 table空间,因此您可能会与其他进行大量排序的会话争用。
这是另一个危险信号:
FOR R1 IN C1 LOOP<br>
... FOR R2 IN C2(R1.ISBN) LOOP
SQL 是一种 set-based 语言。它针对加入 table 和以 highly-performative 方式返回数据集进行了优化。嵌套游标循环意味着 row-by-row 处理,这无疑更容易编码,但可能比等效的集合操作慢几个数量级。
--To check whether Product is exists or not
您有多个查询 select 来自同一个 tables (AN
, 'ANP) using the same criteria (
isbn`)。也许所有这些重复项是验证您的业务规则的唯一方法,但这似乎不太可能。
FINAL_FILNAME := FINAL_FILNAME || V_FILENAME ||',';
也许您可以重写查询以使用 listagg()
而不是使用过程逻辑来连接字符串?
UPDATE GT_ADD_ISBNS
同样,您所有的更新都是单行操作而不是集合操作。
"Is there any way to make this process faster in the stored procedure itself by doing batch process?"
在不了解您的规则和上下文的情况下,我们无法为您重写您的逻辑,但是 15-16 小时对于此来说太长了,因此您绝对可以减少经过的时间。
需要考虑的事项:
- 用您用来填充它的查询替换对临时文件 table 的写入和读取
- 重写循环以使用具有高 LIMIT(例如 1000)的 BULK COLLECT 来提高 select 效率。 Find out more.
- 填充数组并使用 FORALL 提高更新效率。 Find out more.
- 通过将逻辑合并到主查询中,使用 OUTER JOIN 语法测试是否存在,尝试删除所有这些个体 look-ups。
这些都是猜测。如果你真的想知道程序把时间花在哪里了——而这些知识是所有成功调整的基础,所以你应该想知道——你应该 运行 PL/SQL Profiler 下的程序.这将告诉您哪些线路花费的时间最多,而这些线路通常是您需要集中精力调整的地方。如果您还没有访问 DBMS_PROFILER 的权限,则需要 DBA 为您 运行 安装脚本。 Find out more.
" can we change this code into Java and run this code in multi threaded mode?"
考虑到减慢程序的原因之一是 I/O 从临时 selecting 的成本 table 很有可能 multi-threading 可能引入进一步的争论实际上让事情变得更糟。您应该首先寻求改进存储过程。
我们正在迭代来自全局临时 table.below 的 100k+ 条记录,存储过程将逐条迭代来自全局临时 table 的所有记录,并且必须处理以下三个步骤。
- 查看产品是否存在
- 查看资产中的产品是否有'category'。
- 查看资产的文件名是否以“%pdf%”开头。
所以每条记录都要经过这3个步骤,最终的文件名会被存储在table中,才算成功记录。如果任何步骤中出现任何错误,则会为该记录存储错误消息。
以下存储过程需要很长时间才能处理,因为它是按顺序处理的。
- 有没有办法通过批处理使存储过程本身的这个过程更快?
- 如果在存储过程中不可行,那么我们可以将这段代码改为Java和运行多线程模式下的这段代码吗?比如创建 10 个线程,每个线程将同时获取一条记录并处理这段代码。如果有人提供一些伪代码,我会很高兴。
建议使用哪种方法?
DECLARE
V_NODE_ID VARCHAR2(20);
V_FILENAME VARCHAR2(100);
V_CATEGORY_COUNT INTEGER :=0;
FINAL_FILNAME VARCHAR2(2000);
V_FINAL_ERRORMESSAGE VARCHAR2(2000);
CURSOR C1 IS
SELECT isbn FROM GT_ADD_ISBNS GT;
CURSOR C2(v_isbn in varchar2) IS
SELECT ANP.NODE_ID NODE_ID
FROM
table1 ANP,
table2 ANPP,
table3 AN
WHERE
ANP.NODE_ID=AN.ID AND
ANPP.NODE_ID=ANP.NODE_ID AND
AN.NAME_ID =26 AND
ANP.CATEORGY='category' AND
ANP.QNAME_ID='categories' AND
ANP.NODE_ID IN(SELECT CHILD_NODE_ID
FROM TABLE_ASSOC START WITH PARENT_NODE_ID IN(v_isbn)
CONNECT BY PRIOR CHILD_NODE_ID = PARENT_NODE_ID);
BEGIN
--Iterating all Products
FOR R1 IN C1
LOOP
FINAL_FILNAME :='';
BEGIN
--To check whether Product is exists or not
SELECT AN.ID INTO V_NODE_ID
FROM TABLE1 AN,
TABLE2 ANP
WHERE
AN.ID=ANP.NODE_ID AND
ANP.VALUE in(R1.ISBN);
V_CATEGORY_COUNT :=0;
V_FINAL_ERRORMESSAGE :='';
--To check Whether Product inside the assets are having the 'category' is applied or not
FOR R2 IN C2(R1.ISBN)
LOOP
V_CATEGORY_COUNT := V_CATEGORY_COUNT+1;
BEGIN
--In this Logic Product inside the assets have applied the 'category' But those assets are having documents LIKE '%pdf%' or not
SELECT ANP.STRING_VALUE into V_FILENAME
FROM
table1 ANP,
table2 ANPP,
table3 ACD
WHERE
ANP.QNAME_ID=21 AND
ACD.ID=ANPP.LONG_VALUE
ANP.NODE_ID=ANPP.NODE_ID AND
ANPP.QNAME_ID=36 AND
ANP.STRING_VALUE LIKE '%pdf%' AND
ANP.NODE_ID=R2.NODE_ID;
FINAL_FILNAME := FINAL_FILNAME || V_FILENAME ||',';
EXCEPTION WHEN
NO_DATA_FOUND THEN
V_FINAL_ERRORMESSAGE:=V_FINAL_ERRORMESSAGE|| 'Category is applied for this Product But for the asset:'|| R2.NODE_ID || ':Documents[LIKE %pdf%] were not found ;';
UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE= V_FINAL_ERRORMESSAGE WHERE ISBN= R1.ISBN;
END;--Iterating for each NODEID
END LOOP;--Iterating the assets[Nodes] for each product of catgeory
-- DBMS_OUTPUT.PUT_LINE('R1.ISBN:' || R1.ISBN ||'::V_CATEGORY_COUNT:' || V_CATEGORY_COUNT);
IF(V_CATEGORY_COUNT = 0) THEN
UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE= 'Category is not applied to none of the Assets for this Product' WHERE ISBN= R1.ISBN;
END IF;
EXCEPTION WHEN
NO_DATA_FOUND THEN
UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE= 'Product is not Found:' WHERE ISBN= R1.ISBN;
END;
-- DBMS_OUTPUT.PUT_LINE( R1.ISBN || 'Final documents:'||FINAL_FILNAME);
UPDATE GT_ADD_ISBNS SET FILENAME=FINAL_FILNAME WHERE ISBN= R1.ISBN;
COMMIT;
END LOOP;--looping gt_isbns
END;
您有许多潜在的性能问题。这是一个:
"We are iterating 100k+ records from global temporary table"
全局临时 tables 可能会很慢。填充它们意味着将所有数据写入磁盘;从他们那里读取意味着从磁盘读取。很多 I/O 可能是可以避免的。此外,GTT 使用 临时 table空间,因此您可能会与其他进行大量排序的会话争用。
这是另一个危险信号:
FOR R1 IN C1 LOOP<br> ... FOR R2 IN C2(R1.ISBN) LOOP
SQL 是一种 set-based 语言。它针对加入 table 和以 highly-performative 方式返回数据集进行了优化。嵌套游标循环意味着 row-by-row 处理,这无疑更容易编码,但可能比等效的集合操作慢几个数量级。
--To check whether Product is exists or not
您有多个查询 select 来自同一个 tables (AN
, 'ANP) using the same criteria (
isbn`)。也许所有这些重复项是验证您的业务规则的唯一方法,但这似乎不太可能。
FINAL_FILNAME := FINAL_FILNAME || V_FILENAME ||',';
也许您可以重写查询以使用 listagg()
而不是使用过程逻辑来连接字符串?
UPDATE GT_ADD_ISBNS
同样,您所有的更新都是单行操作而不是集合操作。
"Is there any way to make this process faster in the stored procedure itself by doing batch process?"
在不了解您的规则和上下文的情况下,我们无法为您重写您的逻辑,但是 15-16 小时对于此来说太长了,因此您绝对可以减少经过的时间。
需要考虑的事项:
- 用您用来填充它的查询替换对临时文件 table 的写入和读取
- 重写循环以使用具有高 LIMIT(例如 1000)的 BULK COLLECT 来提高 select 效率。 Find out more.
- 填充数组并使用 FORALL 提高更新效率。 Find out more.
- 通过将逻辑合并到主查询中,使用 OUTER JOIN 语法测试是否存在,尝试删除所有这些个体 look-ups。
这些都是猜测。如果你真的想知道程序把时间花在哪里了——而这些知识是所有成功调整的基础,所以你应该想知道——你应该 运行 PL/SQL Profiler 下的程序.这将告诉您哪些线路花费的时间最多,而这些线路通常是您需要集中精力调整的地方。如果您还没有访问 DBMS_PROFILER 的权限,则需要 DBA 为您 运行 安装脚本。 Find out more.
" can we change this code into Java and run this code in multi threaded mode?"
考虑到减慢程序的原因之一是 I/O 从临时 selecting 的成本 table 很有可能 multi-threading 可能引入进一步的争论实际上让事情变得更糟。您应该首先寻求改进存储过程。