本帖最后由 wxjzqym 于 2012-4-25 10:38 编辑
环境描述: OS/WinXP DB/Oracle 10.2.0.1(32bit)
实验如下:
1.准备工作,创建两张表以及一个序列和自定义函数f
sqlplus scott/tiger
create table call_t(id int,txt varchar2(100));
create table query_t as select rownum rn from emp;
create sequence s;
create or replace function f return number
as
pragma autonomous_transaction;
begin
insert into call_t values ( s.nextval, 'i was called ' );
commit;
return 99999;
end;
/
2.执行"select * from query_t where rn=f"该sql,然后查询t_call表中的行数
2.1先确认当前情况下表中的记录数:
SQL> select count(*) from call_t;
COUNT(*)
----------
0
SQL> select count(*) from query_t;
COUNT(*)
----------
12
2.2执行sql:
SQL> select * from query_t where rn=f;
未选定行
SQL> select count(*) from call_t;
COUNT(*)
----------
12
从call_t中的记录数发现f函数被调用了12次,正好是query_t表中的记录数。
3.在query_t表中创建索引后再次执行同样sql
3.1先在query_t表中创建索引:
SQL> create index t_id on query_t(rn);
索引已创建。
3.2执行sql:
SQL> select * from query_t where rn=f;
未选定行
SQL> select count(*) from call_t;
COUNT(*)
----------
14
当在query_t表中创建索引后,发现f只被调用了两次(通过call_t表中的前后记录比较可知)
select * from query_t where rn=f统计信息以及执行计划如下(通过sql_trace所得)
select *
from
query_t where rn=f
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 1 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 1 0 0
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 61
Rows Row Source Operation
------- ---------------------------------------------------
0 INDEX RANGE SCAN T_ID (cr=3 pr=0 pw=0 time=444 us)(object id 52577)
疑问:执行计划走索引时为什么触发了f两次,是根据cr读的数量还是索引的高度决定的?自己随后也做了
相关实验,随着索引的高度从1到3,cr的量也在不断增加,可是f始终被调用两次。。 请高手给予解释,到底
自定义函数f在有索引的情况下触发的条件是什么?