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进行哈希连接。