使用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;
/

原文地址:https://www.cnblogs.com/wait4friend/p/2334566.html