oracle 使用rownum减少自定义函数的调用

ROWNUM Pseudocolumn --rownum 伪列
For each row returned by a query, the  ROWNUM  pseudocolumn returns a number 

indicating the order in which Oracle selects the row from a table or set of joined rows. 

---每一个查询的返回的行都会带有一个伪列

---伪劣的编号从一开始,从下面的例子可以得出,rownum是从1开始递增如果下一行有值则返回。

scott@ORCL> select * from dept where rownum>5;


no rows selected


scott@ORCL> select * from dept where rownum<5;


    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON



scott@ORCL> create table t1
  2  ( prc_chk_key number(9) not null,
  3   prod_key     number(12) not null,
  4    cmpt_loc_key number(5) not null,
  5    loc_key     number(5)  not null,
  6     prc_chk_dt date
  7  )
  8  /

Table created.


scott@ORCL> insert into t1 select 2,3,4,5,sysdate
  2  from all_objects where rownum<=50;
from all_objects where rownum<=50

scott@ORCL> create table t2
  2  (prc_chk_key number(9) not null,
  3   prc_chk_typ_desc varchar2(35) not null,
  4   cmpt_loc_key  number(5),
  5   loc_key  number(5) not null
  6  ) 
  7  /

scott@ORCL> insert into t2 select  2,'x', 4,5 from all_objects where rownum<=50;

现在我们创建一个函数,返回值为一个常量,使用dbms_application_info 使返回值每次都加1,能够

是我们看到函数F被调用了多少次。

 1  create or replace function F(
  2  v_prod_key  in number default null,
  3  v_proc_chk_key IN number default NULL,
  4  v_return  IN varchar2 default null,
  5  v_want_sr IN  varchar2 default  null,
  6  v_version  IN number) RETURN varchar2
  7  AS
  8   BEGIN
  9   DBMS_APPLICATION_info.set_client_info(userenv('client_info')+1);
 10  return 'x';
 11* end;
scott@ORCL> /




scott@ORCL> EXEC DBMS_APPLICATION_info.set_client_info(0);


  1  select /*+ use_hash(al1,al2) */
  2  al2.prc_chk_typ_desc prc_chk_type_desc,
  3  al1.prc_chk_dt  prc_chk_dt,
  4  al1.cmpt_loc_key  cmpt_loc_key,
  5  al1.prod_key  upc_prod_key,
  6  al1.loc_key  loc_key,
  7  max(F(al1.PROD_KEY,al1.prc_chk_key,'QTY','D',1)),
  8  max(F(al1.PROD_KEY,al1.prc_chk_key,'AMT','D',1)),
  9  max(F(al1.PROD_KEY,al1.prc_chk_key,'CODE','D',1)),
 10  max(F(al1.PROD_KEY,al1.prc_chk_key,'PRC','D',1))
 11  from t1 al1,t2 al2
 12  where al1.cmpt_loc_key=al2.cmpt_loc_key
 13  and al1.loc_key=al2.loc_key
 14  and al1.prc_chk_key =al2.prc_chk_key
 15  group by al2.prc_chk_typ_desc,al1.prc_chk_dt,al1.cmpt_loc_key,al1.prod_key,
 16* al1.loc_key
scott@ORCL> /




Execution Plan
----------------------------------------------------------
Plan hash value: 2197463864


----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |    50 |  5950 |     8  (25)| 00:00:01 |
|   1 |  SORT GROUP BY      |      |    50 |  5950 |     8  (25)| 00:00:01 |
|*  2 |   HASH JOIN         |      |    50 |  5950 |     7  (15)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| T1   |    50 |  3050 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| T2   |    50 |  2900 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - access("AL1"."CMPT_LOC_KEY"="AL2"."CMPT_LOC_KEY" AND
              "AL1"."LOC_KEY"="AL2"."LOC_KEY" AND
              "AL1"."PRC_CHK_KEY"="AL2"."PRC_CHK_KEY")


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         51  recursive calls
          0  db block gets
        117  consistent gets
          0  physical reads
          0  redo size
       1289  bytes sent via SQL*Net to client
        519  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

现在我们查看函数被调用了几次

scott@ORCL> select userenv('client_info') data from dual;


DATA
----------------------------------------------------------------
10000

如果行数远远多于五十的话那么函数的调用次数将是相当惊人的。

下面我们重写这条sql语句,先初始化环境。

scott@ORCL> EXEC DBMS_APPLICATION_info.set_client_info(0);


 1   select /*+ use_hash(al1,al2) */
  2      al2.prc_chk_typ_desc prc_chk_type_desc,
  3      al1.prc_chk_dt  prc_chk_dt,
  4      al1.cmpt_loc_key  cmpt_loc_key,
  5      al1.prod_key  upc_prod_key,
  6      al1.loc_key  loc_key,
  7      max(a),
  8      max(b),
  9     max(c),
 10     max(d)
 11     from (
 12     select al1.*,
 13   F(al1.PROD_KEY,al1.prc_chk_key,'QTY','D',1) a,
 14   F(al1.PROD_KEY,al1.prc_chk_key,'AMT','D',1) b,
 15   F(al1.PROD_KEY,al1.prc_chk_key,'CODE','D',1) c,
 16   F(al1.PROD_KEY,al1.prc_chk_key,'PRC','D',1) d,
 17   ROWNUM r from t1 al1
 18  ) al1,t2 al2
 19     where al1.cmpt_loc_key=al2.cmpt_loc_key
 20     and al1.loc_key=al2.loc_key
 21     and al1.prc_chk_key =al2.prc_chk_key
 22     group by al2.prc_chk_typ_desc,al1.prc_chk_dt,al1.cmpt_loc_key,al1.prod_key,
 23*   al1.loc_key
scott@ORCL> /




Execution Plan
----------------------------------------------------------
Plan hash value: 2566946263


------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |  2500 |    19M|     8  (25)| 00:00:01 |
|   1 |  SORT GROUP BY        |      |  2500 |    19M|     8  (25)| 00:00:01 |
|*  2 |   HASH JOIN           |      |  2500 |    19M|     7  (15)| 00:00:01 |
|   3 |    TABLE ACCESS FULL  | T2   |    50 |  2900 |     3   (0)| 00:00:01 |
|   4 |    VIEW               |      |    50 |   393K|     3   (0)| 00:00:01 |
|   5 |     COUNT             |      |       |       |            |          |
|   6 |      TABLE ACCESS FULL| T1   |    50 |  3050 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   2 - access("AL1"."CMPT_LOC_KEY"="AL2"."CMPT_LOC_KEY" AND
              "AL1"."LOC_KEY"="AL2"."LOC_KEY" AND
              "AL1"."PRC_CHK_KEY"="AL2"."PRC_CHK_KEY")


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         55  recursive calls
          0  db block gets
        158  consistent gets
          0  physical reads
          0  redo size
       1120  bytes sent via SQL*Net to client
        519  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

查看函数被调用的此次数

scott@ORCL> select userenv('client_info') data from dual;


DATA
----------------------------------------------------------------
200


第二sql语句在内联视图中使用了rownum,oracle为了分配rownum给每一行必须实体化内联视图。从执行计划中可以看到

t1进行全表扫描然后转化为实体化视图,结果集合t2进行哈希连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值