批量收集的最佳语法

时间:2016-10-29 17:48:43

标签: sql oracle

我想知道是否有更好或更好的方式来编写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

谢谢!

1 个答案:

答案 0 :(得分:1)

为什么没有批量收集会更快?因为您对从光标获取的数据不执行任何操作。通常,一个人在更新/插入数据时使用批量收集来批量处理它,而不是逐行处理。尝试在循环中执行,将这些行插入到另一个表中,然后您就会看到差异。

哪种方式更好?这取决于您的要求。对我而言,最有意义的解决方案是限制。如果我要像1和2那样处理整套数据,为什么要批量收集?这可能意味着我能够在一个庞大的声明中处理数据。如果使用限制,您可以优化批次大小以获得最佳的处理数据性能。此外,限制有助于在插入速度和锁定表的时间之间找到折衷方式,以便进行插入/更新。

相关问题