zoukankan      html  css  js  c++  java
  • 使用pipeline的函数

    使用pipeline和并行的存储过程,记录一下。

    Parallel Query应该满足两个条件
        1。大的,运行时间很长的查询
        2。有足够的系统资源
    parallel query is essentially nonscalable.如果有很多用户执行pq,那么实际效果会很差,因为
    很多用户会造成系统资源的竞争。比如在OLTP里面,qc就不合适。


    Parallel DML
    必须显式指定 alter session enable parallel dml;否则不会发生   


    Parallel DDL
    可以并行的DDL(9i)
         create index
         create table as select
         alter index rebuild
         alter table move
         alter table split|coalesce partition
         alter index split partition
         
         
    ------------------------------------------------------------------------
    ---改写串行存储过程,使用管道函数和并行     ------------------------------------------
    ------------------------------------------------------------------------     

    使用的表结构如下
    test@DW> desc t1
     Name                                                              Null?    Type
     ----------------------------------------------------------------- -------- --------------------------------------------
     X                                                                          NUMBER
     Y                                                                          VARCHAR2(128)
     Z                                                                          VARCHAR2(19)

    test@DW> desc t2
     Name                                                              Null?    Type
     ----------------------------------------------------------------- -------- --------------------------------------------
     X                                                                          NUMBER
     Y                                                                          VARCHAR2(128)
     Z                                                                          VARCHAR2(19)
     SID                                                                        NUMBER
     
    test@DW> exec dbms_stats.gather_table_stats(user,'T1',cascade=>true);

    test@DW> select count(1) from t1;

      COUNT(1)
    ----------
        200000

    --======================================
    原始sp如下,一个标准的串行sp
    CREATE OR REPLACE PROCEDURE p1 AS
      v_x   NUMBER;
      v_sid NUMBER;
    BEGIN
      SELECT sid INTO v_sid FROM v$mystat WHERE rownum = 1;

      FOR c IN (SELECT x, y, z FROM t1) LOOP
        v_x := (c.x + c.x - c.x + c.x - c.x + c.x - c.x + c.x - c.x + c.x - c.x);
        INSERT INTO t2 (x, y, z, sid) VALUES (v_x, c.y, c.z, v_sid);
      END LOOP;
      COMMIT;
    END;

    test@DW> truncate table t2;

    Table truncated.

    test@DW> exec p1;

    PL/SQL procedure successfully completed.

    Elapsed: 00:00:19.45
    test@DW> select sid,count(1) from t2 group by sid;

           SID   COUNT(1)
    ---------- ----------
           145     200000


    --========================================
    建立一个type
    test@DW> CREATE OR REPLACE TYPE t2_type AS OBJECT
      2  (
      3    x   NUMBER,
      4    y   VARCHAR2(120),
      5    z   VARCHAR2(19),
      6    sid NUMBER
      7  )
      8  /

    Type created.

    test@DW> create or replace type t2_tab as table of t2_type
      2  /

    Type created.    

    --建立pipeline的函数
    CREATE OR REPLACE FUNCTION f2(l_cur IN SYS_REFCURSOR) RETURN t2_tab
      PIPELINED
      PARALLEL_ENABLE(PARTITION l_cur BY ANY) IS
      v_x   NUMBER;
      v_sid NUMBER;
      v_rec t1%ROWTYPE;
    BEGIN
      SELECT sid INTO v_sid FROM v$mystat WHERE rownum = 1;
      LOOP
        FETCH l_cur
          INTO v_rec;
        EXIT WHEN l_cur%NOTFOUND;
        v_x := (v_rec.x + v_rec.x - v_rec.x + v_rec.x - v_rec.x + v_rec.x -
               v_rec.x + v_rec.x - v_rec.x + v_rec.x - v_rec.x);
        PIPE ROW(t2_type(v_x, v_rec.y, v_rec.z, v_sid));
      END LOOP;
      CLOSE l_cur;
      RETURN;
    END;

    --直接使用
    --从测试结果来看,即使不使用并行调用,pipeline函数在执行时间上也比原来的方法快100%(9s vs 19s)
    test@DW> truncate table t2;

    Table truncated.

    test@DW> insert into t2(x,y,z,sid) select * from table(f2(cursor(select * from t1)));

    200000 rows created.

    Elapsed: 00:00:08.45

    test@DW> select sid,count(1) from t2 group by sid;

           SID   COUNT(1)
    ---------- ----------
           145     200000


    --并行使用
    --使用并行后(从结果的sid可以看出degree是2),时间有一点减少(7s vs 9s)
    test@DW> truncate table t2;

    Table truncated.

    test@DW> insert into t2(x,y,z,sid) select * from table(f2(cursor(select /*+parallel(t1)*/ * from t1)));

    200000 rows created.

    Elapsed: 00:00:06.92

    test@DW> select sid,count(1) from t2 group by sid;

           SID   COUNT(1)
    ---------- ----------
           143     101947
           137      98053

    ------------------------------------------------------------------------------------------
    今天看到一个使用pipelined的例子,纪录下
    create or replace type str2tblType as table of varchar2(30);
    /
    create or replace
    function str2tbl( p_str in varchar2, p_delim in varchar2 default ',' )
    return str2tblType
    PIPELINED
    as
        l_str      long default p_str || p_delim;
        l_n        number;
    begin
        loop
            l_n := instr( l_str, p_delim );
            exit when (nvl(l_n,0) = 0);
                    pipe row ( ltrim(rtrim(substr(l_str,1,l_n-1))) );
            l_str := substr( l_str, l_n+1 );
        end loop;
        return;
    end;
    /

  • 相关阅读:
    一本通1331后缀表达式的值
    一本通1198 逆波兰表达式
    一本通1311 求逆序对(归并排序应用)
    快速排序
    一本通1310 车厢重组(冒泡排序,类似逆序对)
    一本通1186 出现次数超过一半的数(类似桶排序)
    一本通1216 红与黑 (代码没有参考任何博客,完全是自己写的,我搜索出山了!!!)
    一本通1222 放苹果
    一本通 1212 LETTERS
    一本通1215 迷宫
  • 原文地址:https://www.cnblogs.com/wait4friend/p/2334566.html
Copyright © 2011-2022 走看看