我在使用PL / SQL中的Bulk Bind时遇到问题。基本上我想要的是一个表(Component)来更新它的fieldvalue依赖于Component_id和fieldname。所有这些都作为参数传递(varchar2_nested_table类型实际上是字符串数组,每个更新语句需要一个元素)。因此,例如,如果Component_id ='Compid1'和fieldname ='name',则fieldvalue应更新为'新组件名称'。
我输入了与此http://www.oracle.com/technetwork/issue-archive/o14tech-plsql-l2-091157.html相关的以下代码。代码可以工作,但并不比一个简单的循环更快,它为IN参数中的每个元素执行更新。因此,如果参数有1000个元素,那么将执行1000个更新语句。我也意识到我没有使用BULK COLLECT INTO,但我认为我不需要它,因为我不需要从数据库中选择任何东西,只需更新。
此刻,两次更新需要4-5秒。我假设我正在错误地使用批量绑定或者对主题有误解,例如我可以发现人们在2秒内执行了50,000行等等。据我所知,FORALL应该通过减少上下文切换次数来提高性能。我尝试了另一种使用游标和大量绑定在线发现的方法,但结果相同。也许我的表现期望太高了?我不认为看到别人的结果。任何帮助将不胜感激。
create or replace procedure BulkUpdate(sendSubject_in IN varchar2_nested_table_type,
fieldname_in IN varchar2_nested_table_type,fieldvalue_in IN varchar2_nested_table_type) is
TYPE component_aat IS TABLE OF component.component_id%TYPE
INDEX BY PLS_INTEGER;
TYPE fieldname_aat IS TABLE OF component.fieldname%TYPE
INDEX BY PLS_INTEGER;
TYPE fieldvalue_aat IS TABLE OF component.fieldvalue%TYPE
INDEX BY PLS_INTEGER;
fieldnames fieldname_aat;
fieldvalues fieldvalue_aat;
approved_components component_aat;
PROCEDURE partition_eligibility
IS
BEGIN
FOR indx IN sendSubject_in.FIRST .. sendSubject_in.LAST
LOOP
approved_components(indx) := sendSubject_in(indx);
fieldnames(indx):= fieldname_in(indx);
fieldvalues(indx) := fieldvalue_in(indx);
END LOOP;
END;
PROCEDURE update_components
IS
BEGIN
FORALL indx IN approved_components.FIRST .. approved_components.LAST
UPDATE Component
SET Fieldvalue = fieldvalues(indx)
WHERE Component_id = approved_components(indx)
AND Fieldname = fieldnames(indx);
END;
BEGIN
partition_eligibility;
update_components;
END BulkUpdate;
答案 0 :(得分:0)
还有其他事情发生,我怀疑你的个人更新都会花费很多时间,可能是因为有触发器或效率低下的索引。 (请注意,如果每个语句单独使用,使用批量更新将不会为您节省大量时间,因为与实际工作相比,上下文切换可忽略不计)。
这是我的测试设置:
CREATE TABLE Component (
Component_id NUMBER,
fieldname VARCHAR2(100),
Fieldvalue VARCHAR2(100),
CONSTRAINT component_pk PRIMARY KEY (component_id, fieldname)
);
-- insert 1 million rows
INSERT INTO component
(SELECT ROWNUM, to_char(MOD(ROWNUM, 100)), dbms_random.string('p', 10)
FROM dual
CONNECT BY LEVEL <= 1e6);
CREATE OR REPLACE TYPE varchar2_nested_table_type AS TABLE OF VARCHAR2(100);
/
SET SERVEROUTPUT ON SIZE UNLIMITED FORMAT WRAPPED
DECLARE
l_id varchar2_nested_table_type;
l_names varchar2_nested_table_type;
l_value varchar2_nested_table_type;
l_time NUMBER;
BEGIN
SELECT rownum, to_char(MOD(rownum, 100)), dbms_random.STRING('p', 10)
BULK COLLECT INTO l_id, l_names, l_value
FROM dual
CONNECT BY LEVEL <= 100000;
l_time := dbms_utility.get_time;
BulkUpdate(l_id, l_names, l_value);
dbms_output.put_line((dbms_utility.get_time - l_time) || ' cs elapsed.');
END;
/
在不起眼的测试机器上,大约1.5秒内更新了100000行。逐行更新相同的数据集大约需要4秒钟。
您可以使用新创建的表运行类似的脚本吗?
答案 1 :(得分:0)
每当我们将OP / SQL块提交到oracle服务器时,总是会执行SQL语句。通过SQL引擎和程序语句执行。通过程序声明执行者。这个程序语句执行器在PL / SQL引擎中可用,每当我们通过SQL使用大量加载时,PL / SQL语句总是oracle服务器通过这些引擎分别执行这些语句。
这种类型的执行方法总是内容切换执行方法会降低应用程序的性能。为了解决这个问题,oracle使用集合引入了“批量绑定”进程,即在此方法中,oracle服务器一次执行所有SQL语句。 批量收集:
每当我们自动使用此子句时。 Oracle服务器选择日期并将其存储到集合中。
中使用的批量收集条款