【问题标题】:Which is better - Cursor For Loop or Loop over PLSQL collection populated by Bulk Collect?哪个更好 - Cursor For Loop 或 Loop over 由 Bulk Collect 填充的 PLSQL 集合?
【发布时间】:2013-10-03 10:07:24
【问题描述】:

哪个性能更好。

版本 1 使用 Cursor For Loop

DECLARE
  total_val number(6);

  CURSOR c1 IS
  SELECT * FROM emp
  ;
BEGIN
  total_val := 0;
  FOR emp_rec IN c1
  LOOP
    total_val := total_val + emp_rec.sal;
  END LOOP;

  DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
END;

版本 2 首先使用 Bulk Collect 将所有行放入 PLSQL 集合,然后对其进行迭代。

DECLARE
  total_val number(6);

  CURSOR c1 IS
  SELECT * FROM emp
  ;

  TYPE emp_recs_type IS TABLE OF emp%ROWTYPE;
  emp_recs emp_recs_type;
BEGIN
  total_val := 0;

  OPEN c1;
  FETCH c1 BULK COLLECT INTO emp_recs;
  CLOSE c1;

  FOR l_index IN emp_recs.FIRST..emp_recs.LAST
  LOOP
    total_val := total_val + emp_recs(l_index).sal;
  END LOOP;

  DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
END;

请假设Cursor 可能返回许多行,可能是成千上万或更多。

【问题讨论】:

    标签: sql plsql oracle11g


    【解决方案1】:

    找出答案的最佳方法是设置一个实验并尝试一下。

    当然,对于您的示例,最好的代码是:

    DECLARE
      total_val number(6);
    BEGIN
      SELECT SUM(sal) INTO total_val FROM emp;
    
      DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
    END;
    

    但是,我知道这只是一个简单的例子!

    理论上使用 BULK COLLECT 应该会更好,但实际上现在(肯定是在 11G 中)Oracle 在后台默默地批量提取 100 行的批次 - 请参阅 this AskTom thread

    如果您自己使用 BULK COLLECT 并且可能存在未指定的行数,您应该使用 LIMIT 子句,否则您可能会遇到内存问题。对于您的示例,这将类似于:

    DECLARE
      total_val number(6);
    
      CURSOR c1 IS
      SELECT * FROM emp
      ;
    
      TYPE emp_recs_type IS TABLE OF emp%ROWTYPE;
      emp_recs emp_recs_type;
    BEGIN
      total_val := 0;
    
      OPEN c1;
    
      LOOP
        FETCH c1 BULK COLLECT INTO emp_recs LIMIT 100;
    
        EXIT WHEN c1.COUNT = 0;
    
        FOR l_index IN emp_recs.FIRST..emp_recs.LAST
        LOOP
          total_val := total_val + emp_recs(l_index).sal;
        END LOOP;
    
      END LOOP;
    
      DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
      CLOSE c1;
    END;
    

    【讨论】:

    • 我认为您的意思是 SUM(sal) 而不是 COUNT(*)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 2018-11-29
    • 1970-01-01
    相关资源
    最近更新 更多