我想知道是否有更好或更好的方式来编写Bulk Collects。 我已经看到了不同的方法,其中一些在下面的示例代码中:
set serveroutput on;
declare
cursor ext_data_file is
select *
from PER_ALL_PEOPLE_F;
TYPE type_emp_rec_ext IS TABLE OF ext_data_file%ROWTYPE index by pls_integer;
l_emp_tab_ext_raw type_emp_rec_ext;
l_emp_tab_ext_clean type_emp_rec_ext;
l_start number;
l_count number := 0;
l_count2 number := 0;
begin
/* Regular Cursor Fetch */
l_start := DBMS_UTILITY.get_time;
FOR cur_rec IN ext_data_file LOOP
l_count2 := l_count2 + 1;
END LOOP;
DBMS_OUTPUT.put_line('Regular (' || l_count2 || ' rows): ' || (DBMS_UTILITY.get_time - l_start) ||' ms');
/* Bulk Collect 1 */
l_start := DBMS_UTILITY.get_time;
open ext_data_file;
fetch ext_data_file
bulk collect
into l_emp_tab_ext_raw;
close ext_data_file;
DBMS_OUTPUT.put_line('Bulk 1 (' || l_emp_tab_ext_raw.count || ' rows): ' || (DBMS_UTILITY.get_time - l_start) ||' ms');
/* Bulk Collect 2 */
l_start := DBMS_UTILITY.get_time;
SELECT *
BULK COLLECT INTO
l_emp_tab_ext_clean
FROM PER_ALL_PEOPLE_F;
DBMS_OUTPUT.put_line('Bulk 2 (' || l_emp_tab_ext_raw.count || ' rows): ' || (DBMS_UTILITY.get_time - l_start) ||' ms');
/* Bulk Collect 3 */
l_start := DBMS_UTILITY.get_time;
OPEN ext_data_file;
LOOP
FETCH ext_data_file
BULK COLLECT INTO l_emp_tab_ext_raw LIMIT 1000;
l_count := l_emp_tab_ext_raw.count + l_count;
EXIT WHEN l_emp_tab_ext_raw.count = 0;
END LOOP;
CLOSE ext_data_file;
DBMS_OUTPUT.put_line('Bulk 3 (' || l_count || ' rows): ' || (DBMS_UTILITY.get_time - l_start) ||' ms');
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(sqlerrm);
end;
在表现方面,我惊讶地发现存在差异。常规提取比批量收集更快!
Regular (1202666 rows): 4174 ms
Bulk 1 (1202666 rows): 6369 ms
Bulk 2 (1202666 rows): 7204 ms
Bulk 3 (1202666 rows): 4380 ms
以下是我的观察:
Bulk Collect 1 : Commonly used when using an Explicit Cursor and has no LIMIT Clause. Also when the cursor Involves numerous Joined Tables.
Bulk Collect 2 : Commonly used when using a single table or an Implicit Cursor and has no LIMIT Clause.
Bulk Collect 3 : Commonly used when using an Explicit Cursor and has a LIMIT Clause.
请确认以上观察结果是否正确。
我的问题是:
1. Why is the Regular Fetch Faster?
2. Which of these Bulk Collects are the Best Syntax to Use in Terms of Overall Performance and Memory Consumption)
我一直在使用语法1,但我认为最好的是语法3。
数据库详细信息:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
谢谢!
答案 0 :(得分:1)
为什么没有批量收集会更快?因为您对从光标获取的数据不执行任何操作。通常,一个人在更新/插入数据时使用批量收集来批量处理它,而不是逐行处理。尝试在循环中执行,将这些行插入到另一个表中,然后您就会看到差异。
哪种方式更好?这取决于您的要求。对我而言,最有意义的解决方案是限制。如果我要像1和2那样处理整套数据,为什么要批量收集?这可能意味着我能够在一个庞大的声明中处理数据。如果使用限制,您可以优化批次大小以获得最佳的处理数据性能。此外,限制有助于在插入速度和锁定表的时间之间找到折衷方式,以便进行插入/更新。