神奇的DUAL表总结
2013-04-25 10:47:24
分类:
Oracle
★★★★★★★★★★★
本文档版权归个人所有,未经允许,禁止用于商业用途,违者必究
★★★★★★★★★★★
背景介绍
:
Oracle DUAL
表
是一个很神奇的东西,为什么说它神奇呢?
DUAL
表属于
SYS
用户,
SYS
用户是专门管理
Oracle
数据字典的用户,
DUAL
表因此属于数据字典的一个组成部分(
而且
DUAL
表是个特殊实现的数据字典表
)。一个
Oracle
使用人员应该知道
SYS
里的东西只能查询,不可乱做修改的,否则会造成意想不到的、甚至毁灭性的灾难。既然
DUAL
表属于数据字典,归
SYS
用户管理,那么其他的用户是如何访问的呢?答案是通过一个叫
DUAL
的
PUBLIC SYNONYM
来访问的。
DUAL
表是建立数据库的时候随数据字典创建而建立的,
它是单行单列的一个表,一般称为“哑表、虚表等”,列名
DUMMY
,类型
VARCHAR2(1)
,值为
'X'
,为什么叫虚表,因为它有比物理表更多神奇内涵。
这就是
DUAL
表的全部基本内容,对于这个基本内容要确保是固定的,不可修改,有很多莫名的问题产生就是因为动了这张表。
DUAL
表的基本内容虽然简单,但背后隐藏了很多神奇的内容,在下面的内容中会详细介绍。
DUAL
表的主要作用是什么呢?有
Oracle
使用经验的都知道,我们
常使用
DUAL
表来计算常量型表达式,
比如用
DUAL
表访问,
SELECT
里可以是
1
、
USER
、
SYSDATE
、
'abc'
、
TRUNC(SYSDATE,'DD')
、
SEQ.NEXTVAL
等这些常量型表达式。因为
DUAL
表就一行,用于计算就很方便了,当然可能有人会问,
DUAL
表计算方便,那么我建立一个只有一行的表
(
多行当然经常不是我们需要的结果
)
,不照样计算方便吗?那是的,当然计算方便,
但是
DUAL
表和
Oracle
优化器有着更紧密的关联
,优化器知道
DUAL
表只有一行,而且很特殊,还有一些优化访问手段,优化器遇到一些计算使用的是
DUAL
或只有一行的普通表,那么优化器的反应很可能是不同的,
DUAL
表的效率要优于那个普通表。另外
DUAL
表常用于结合
CONNECT BY
子句进行数据构造。
DUAL
表是数据字典表,不能乱动,不可对它进行任何
DDL
、
DML
等操作,否则会造成意想不到的效果,比如给
DUAL
插入一条数据,那么执行
DROP TABLE
命令可能会报错,这些都在后面详细讲解,因为它很特殊,你只可对
DUAL
表使用
SELECT
权限,其他权限一律禁止。
内容简介:
1)
DUAL
表常规用途。
主要介绍
DUAL
表有哪些主要用途,比如计算,构造数据等。
2)
DUAL
表神秘之处
介绍在
9i
和
10g
下对
DUAL
进行
DDL
和
DML
操作的神奇表现、
10g
的
FAST DUAL
优化、在
9i
和
10g
下使用
DUAL
和
CONNECT BY
构造数据的一些问题和方法探讨以及其他
DUAL
神秘之处。
3)
PL/SQL
中使用
DUAL
赋值和直接变量赋值的性能区别。
通过测试说明
SELECT ..INTO .. FROM DUAL
与
variable := value
的性能区别。
4)
误删
DUAL
表的恢复过程。
误删
DUAL
表的相关方法介绍。
说明:
本章内容脚本请参考
dual_sample.sql
,未做说明一律在当前版本的
SQL*PLUS
下完成脚本测试,未做说明所有脚本都是在下列版本下执行的:
DINGJUN123>show rel
release 1002000100
DUAL
表的常规用途
DUAL
是单行单列的,这个很特殊,我们常使用它来获取一些常量型值或做一些计算功能,当然
DUAL
还有个重要的作用就是用于数据构造。下面举例说明下
DUAL
表的常见功能。
1)
获取一些系统函数的值
这个用的最多的就是获取
SYSDATE
函数的值,从而返回当前时间了,此外还可以获取
USER
等函数值。如:
DINGJUN123>SELECT SYSDATE FROM DUAL;
SYSDATE
--------------
20-10月
-10
已选择
1
行。
DINGJUN123>SELECT USER FROM DUAL;
USER
---------------
DINGJUN123
已选择
1
行。
2)
做相关运算
比如用
DUAL
做些数学运算,一些函数测试,获取
sequence
等。如:
--
数学运算,充当计算器
DINGJUN123>SELECT 2*5-10 num FROM DUAL;
NUM
----------
0
已选择
1
行。
--
函数测试,有时候一函数搞不清楚用法,用
DUAL
测试很方便
DINGJUN123>SELECT REPLACE('abcdefg','f','$') rp FROM DUAL;
RP
--------------
abcde$g
已选择
1
行。
--
查找序列,序列是必须要通过
SQL
来查找的,所以用
DUAL
很简单,如果用一个多行的物理表,会有递增的序列出现
DINGJUN123>SELECT seq.nextval FROM DUAL;
NEXTVAL
----------
301
已选择
1
行。
--
用普通物理表,有多少行,就会计算多少次,一般我们不需要这种功能
DINGJUN123>SELECT COUNT(*) FROM t;
COUNT(*)
----------
2
已选择
1
行。
DINGJUN123>SELECT seq.nextval FROM t;
NEXTVAL
----------
302
303
已选择
2
行。
3)
使用
DUAL
表构造数据
使用
DUAL
表构造数据,常结合
CONNECT BY
层次查询来构造,比如现在要构造
1
到
100
之间所有偶数,如下:
DINGJUN123>SELECT LEVEL lv
2 FROM DUAL
3 WHERE MOD(LEVEL,2) = 0
--
注意
WHERE
是在
CONNECT BY
之后执行的,过滤
CONNECT BY
的结果
4 CONNECT BY LEVEL <= 100;
LV
-------------------
2
4
6
---中间结果省略
96
98
100
已选择
50
行。
上面用
DUAL
和
CONNECT BY
实现常见的数据构造,
注意这是在
10g
下完成的,如果是
9i
不一定成功,而且
9i
的不同版本还有不同的表现,这个会在下一节详细讲解
。
再来看一个例子,有时候,我们需要建立些简单的表来进行测试,那当然需要给表插入些测试数据了,使用
DUAL
表,可以很简单地构造些测试数据:
DINGJUN123>DROP TABLE emp_t;
表已删除。
DINGJUN123>CREATE TABLE emp_t
2 AS
3 SELECT 1 id,'liming' name, DATE'2010-10-20' hire_date FROM DUAL UNION ALL
4 SELECT 1 ,'jack',DATE'2010-10-21' FROM DUAL;
表已创建。
使用
DUAL
表很简单吧,用于测试,构造些数据
(
还可以与
DBMS_RANDOM
包配合构造随机数据
)
,的确很方便,当然有很多方法可以实现数据的构造,比如数据直接放
csv
文件里,通过
sql*loader
来导入,或用外部表,也可以通过
plsql developer
等工具提供的快速导入功能(比如
select * from table for update
然后粘贴),但是少量数据还是用
DUAL
简单,它可以保存测试的脚本。下面做一个比较复杂点的
DUAL
表构造随机测试数据:
DUAL
表的神秘之处
DUAL
表是
Oracle
中特殊的数据字典表,它是由
Oracle
内部代码维护的,我们一般情况下看到的
DUAL
表单行单列,字段名为
DUMMY
,类型
VARCHAR2(1)
,这些都是表象,因为
DUAL
表在
Oracle
中的用途很广泛,使用很便利,所以
Oracle
考虑了多方面因素,才造了这么个神奇的“虚表”。你认为
DUAL
表真的是单行单列的吗?先看表象:
SYS>desc dual
名称
是否为空
?
类型
---------- -------- --------------
DUMMY VARCHAR2(1)
SYS>select * from dual;
DU
--
x
已选择
1
行。
表面来看,的确是单行单列,
TOM(TOM KYTE,Oracle VP,
世界知名数据库专家
)
曾经说
DUAL
表之所以做成单行单列只是为了便利,当然
DUAL
表有更多的用途,比如一些系统操作,如
DROP TABLE
,一些系统包等都可能会用到
DUAL
表,你改变了
DUAL
表的属性,比如增强一行,那么可能会导致严重的问题,数据字典都是不能乱动的。
DUAL
表的数据类型和列名以及它的值并没有绝对的关系,这个要注意,
DUAL
表用途广泛,
Oracle
优化器看到
DUAL
表,它就知道
DUAL
表应该是单行单列的,而且会启用相关优化措施
(
这点会在后面的例子中有说明
)
。那么
DUAL
表真的是单行单列的吗?看
TOM
给的一点提示:
--
关闭数据库后,神奇的
DUAL
不同了
SYS>alter database close;
数据库已更改。
SYS>desc dual
名称
是否为空
?
类型
---------- -------- --------------
DUMMY VARCHAR2(1)
SYS>select * from dual;
ADDR INDX INST_ID DU
-------- ---------- ---------- -- ---------- ------
03674AD4 0 1 X
已选择
1
行。
DUAL
表既然是属于
SYS
数据字典,那么普通用户怎么访问到
DUAL
呢,而且还不要加
SCHEMA,
那当然是利用
PUBLIC
同义词了,查看:
SYS> SELECT * FROM DBA_SYNONYMS WHERE TABLE_NAME='DUAL';
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME DB_LINK
-----------------------------------------------------------------------
PUBLIC
DUAL
SYS
DUAL
已选择
1
行。
从上面可以看到,
DUAL
表并没有那么简单。它拥有很多让你
amazing
的特性,当然如果你动了它,它会让你更加地
amazing
。下面就开始
DUAL
表的探秘之旅吧。
1)
在
9i
、
10g
下对
DUAL
进行
DDL
、
DML
操作的神奇表现
前面已经说了,
DUAL
表这种特殊的数据字典,你只可以使用同义词来进行查询操作
(
当然所有的数据字典都不应该乱动
)
,而不能进行其他的操作改变
DUAL
表的基本属性,如果
DUAL
表属性一旦发生变化,可能会造成很多意想不到的问题,下面就暴力改变下
DUAL
表的属性,看看
DUAL
表到底有哪些神奇之处
(
切记,不要在生产环境下实验,后果自负
)
。
先在
9i
下进行相关实验(
增加插入一行,然后
SELECT 'X' FROM DUAL
看看有几行,增加游标迭代
):
--select * from dual
和
select dummy from dual
在
9i
和
10g
下的表现一样,这个不用测试了
SQL>SHOW REL
release 902000400
SQL> select * from dual;
D
-
X
1 row selected.
--
给
DUAL
表插入一行
SQL> insert into dual values('Y');
1 row created.
--
查看全部
DUAL
表内容,
so amazing,
竟然只返回新插入的一行
SQL> select * from dual;
D
-
Y
1 row selected.
--
用
count
查看全部记录数量,正确返回,与上面的对比,
DUAL
表在
SQL*PLUS
里的表现真是很让人迷惑
SQL> select count(*) from dual;
COUNT(*)
----------
2
1 row selected.
SQL> commit;
Commit complete.
已经演示了一些
DUAL
表的神奇表现,下面神奇继续上演:
--
全部清空,再次
amazing,
明明两行,竟然只删除了一行后插入的,当然和上面的
select
不谋而合
SQL> delete from dual;
1 row deleted.
SQL> select * from dual;
D
-
X
1 row selected.
--
继续删除,这下清净了
SQL> delete from dual;
1 row deleted.
SQL> select * from dual;
no rows selected
SQL> select count(*) from dual;
COUNT(*)
----------
0
1 row selected.
--
不能乱删的,恢复吧
SQL> insert into dual values('X');
1 row created.
SQL> select * from dual;
D
-
X
1 row selected.
--
我已经不相信
select * from dual
了,还是
count
一下保险点,正确
SQL> select count(*) from dual;
COUNT(*)
----------
1
1 row selected.
--
对上面的演示继续,这次不用
delete from dual
了,用
delete from dual where dummy='Y',
直接删除掉即可
SQL> insert into dual values('Y');
1 row created.
SQL> commit;
Commit complete.
SQL> select count(*) from dual;
COUNT(*)
----------
2
1 row selected.
SQL> delete from dual where dummy='Y';
1 row deleted.
SQL> commit;
Commit complete.
SQL> select count(*) from dual;
COUNT(*)
----------
1
1 row selected.
--TRUNCATE
和
UPDATE
没有什么神奇的
--TRUNCATE
操作,和
DELETE FROM
不同,
TRUNCATE
在
9.2.4
下能清楚全部
DUAL
数据
--
到
10g
版本测试,
TRUNCATE,UPDATE,DELETE FROM
表现和
9i
一样,但是也有不一样的,请见
10g
版本测试
SQL> insert into dual values('Y');
1 row created.
SQL> commit;
Commit complete.
SQL> truncate table dual;
Table truncated.
SQL> select * from dual;
no rows selected
SQL> select count(*) from dual;
COUNT(*)
----------
0
--
恢复,执行
UPDATE
,可以改变其值
SQL> insert into dual values('X');
1 row created.
Commit complete
SQL> update dual set dummy='Y';
1 row updated
SQL> commit;
Commit complete
SQL> select * from dual;
DUMMY
-----
Y
--
恢复
SQL> update dual set dummy='X';
1 row updated
SQL> commit;
Commit complete
上面演示了在
9.2.4
下对
DUAL
的
INSERT,DELETE,TRUNCATE,UPDATE
操作,可以看出,
DUAL
表的确很神奇,当然在
SQL*PLUS
里新插入一上用
SELECT * FROM DUAL
是看不出到底有几行的,用
COUNT
函数可以,在测试中,我发现在
PLSQL DEVELOPER
工具中用
SELECT * FROM DUAL
是可以看出到底有多少行的,说明
SQL*PLUS
和
DUAL
还是紧密相关的。
DUAL
表多插入了或清空了,那么有什么不利之处呢?不利之处太多了,可能使系统包失效,使一些
DDL
操作报错,使一些程序报错等。下面就继续在
9.2.4
下,用简单的存储过程测试下
DUAL
表多插入了或清空了导致的问题。
SQL> select * from dual;
D
-
X
已选择
1
行。
已用时间
: 00: 00: 00.03
SQL> insert into dual values('Y');
已创建
1
行。
已用时间
: 00: 00: 00.07
SQL> commit;
以上测试只是
9.2.0.4
的情况,下面回到本章
10g
版本,你会发现与
9.2.0.4
很多不同的地方。
SQL>show rel
release 1002000100
SQL>select * from dual;
DU
--
X
已选择 1 行。
SQL>insert into dual values('Y');
已创建 1 行。
SQL>commit;
提交完成。
SQL>select * from dual;
DU
--
Y
已选择 1 行。
--
注意和
9i
测试的对比,
10.2
就算插入了一行记录,
count(*)
仍然不能正确显示行数,还是
1
行,
9i
的为
2
行
SQL>select count(*) from dual;
COUNT(*)
----------
1
已选择 1 行。
--
这个在
9i
显示的是两行,但是
10.2
是
1
行,可以猜测
10.2
多插入了行,在
PL/SQL
里的
select sysdate into .. from dual
--
也不会出问题,这个应该属于
10g
的优化
SQL>select sysdate from dual;
SYSDATE
--------------
31-10月-10
已选择 1 行。
--
从上面可以看出,多插入一行,对
select xxx into variable from dual
是没有影响的。这个在
9i
下是要报
too_many_rows
错误
--
的
DINGJUN123>declare
2 var_date date;
3 begin
4 select sysdate into var_date from dual;
5 dbms_output.put_line(var_date);
6 end;
7 /
31-10月-10
PL/SQL 过程已成功完成。
--DELETE FROM
和
9i
一样,只能删除一行
SQL>delete from dual;
已删除 1 行。
SQL>commit;
提交完成。
SQL>select * from dual;
DU
--
X
已选择 1 行。
SQL>delete from dual;
已删除 1 行。
SQL>commit;
提交完成。
--
将
DUAL
表全清空了,
COUNT
还是只显示
1
行,
DUAL
表除了
select * from dual
或
select dummy from dual
无行显示外,
--
计算是正常的
1
行
--
这个和上面的多插入类似,
9i
也不同
SQL>select count(*) from dual;
COUNT(*)
----------
1
已选择 1 行。
SQL>select * from dual;
未选定行
SYS>select dummy from dual;
未选定行
SQL>select sysdate from dual;
SYSDATE
--------------
31-10月-10
已选择 1 行。
--DUAL
表没有数据了同样不影响
select xxx into variable from dual
,
9i
下测试是报
no_data_found
异常的
DINGJUN123>declare
2 var_date date;
3 begin
4 select sysdate into var_date from dual;
5 dbms_output.put_line(var_date);
6 end;
7 /
31-10月-10
PL/SQL 过程已成功完成。
--TRUNCATE
正常截断,和
9i
一样,当然和上面一样,空
DUAL
表的
COUNT
和相关计算不受影响
SQL>insert into dual values('X');
已创建 1 行。
SQL>insert into dual values('Y');
已创建 1 行。
SQL>commit;
提交完成。
SQL>truncate table dual;
表被截断。
SQL>select * from dual;
未选定行
--
恢复
SQL>insert into dual values('X');
已创建 1 行。
SQL>commit;
提交完成。
下面看看
10g
多插入表对一些
DROP TABLE
操作的影响,当然其他的也可能影响(比如
DROP TABLESPACE
),没有测试而已,测试的目的是说明,
DUAL
表不可欺。
--
多插入一条数据语句省略
DINGJUN123>drop table t;
drop table t
*
第
1
行出现错误
:
ORA-00604: 递归
SQL
级别
1
出现错误
ORA-01422: 实际返回的行数超出请求的行数
返回
ORA-00604
和
ORA-01422
错误,当对表进行
DROP
的时候,看到这两个错误,就要想起是
DUAL
表里的数据多了的缘故。通过
SQL TRACE
可以看到:
select dummy
from
dual where ora_dict_obj_type = 'TABLE'
说明
DUAL
表和
DROP TABLE
操作密切相关,此外
DROP TABLESPACE
也类似,当然可能有其他的操作也相关,这里不测试了。
9i
好检查
DUAL
表数据是不是多了,一个
COUNT
搞定,在
10g
下测试
COUNT
还是返回一条,那么怎么办呢?有很多方式可以看到
DUAL
表的真正记录数,如到
PLSQL DEVELOPER
工具下查看,或用
PL/SQL
的游标解决。如下:
1)
PL/SQL DEVELOPER
可以正确显示
10g
下的
DUAL
表记录数
2)
采用游标迭代
为什么不直接在
PL/SQL
里
select sysdate into..
等方式查看呢
?
前面测试了,
10g
下的
DUAL
不管是数据多了还是数据少了,
select sysdate into … from dual
显示的都是
1
行,而
select dummy into … from dual
如果清空了则不返回数据,多了的话也只显示
1
行,所以用迭代的方式。
DINGJUN123>select count(*) from dual;
COUNT(*)
----------
1
已选择
1
行。
DINGJUN123>set serveroutput on
DINGJUN123>begin
2
for rec in (select dummy from dual) loop
3 dbms_output.put_line(rec.dummy);
4 end loop;
5 end;
6 /
X
Y
PL/SQL 过程已成功完成。
通过测试
9i
和
10g
相应版本的
DUAL
操作,可以看出,
9i
到
10g
变化还是挺大的,
9i
下多插入或清空了
DUAL
表数据影响
SELECT COUNT(*) FROM DUAL
以及类似于
SELECT SYSDATE FROM DUAL
之类的操作,多插入了不影响
DROP TABLE
等操作。但是在
10.2
的测试下可以看出,多插入或清空不影响上述
COUNT
和计算操作,但是多插入了,则影响
DROP TABLE
等操作
(
清空了不影响
DROP TABLE
操作
)
,当然清空了影响
SELECT * FROM DUAL
或
SELECT DUMMY FROM DUAL
,但是不影响类似于
SELECT SYSDATE FROM DUAL
。此外,
10g
下在
PL/SQL
里用隐式游标迭代查找
DUAL
表里的数据,和
9i
表现一样。
3)
10g
的
FAST DUAL
优化
9i
下的
DUAL
表访问没有优化,一般逻辑读为
3
。
10g
的
DUAL
表如果不需要访问
DUAL
表里的内容
,
而是利用
DUAL
表的一些功能,比如
select sysdate from dual
,
则会采用
FAST DUAL
方式来访问表,它不是真正的访问表,因此逻辑读为
0
,这样在一个高频
DUAL
表使用的系统中,会大量减少逻辑读。
9i
下
DUAL
的访问方式是:
--
不管是只访问
dual
表本身的内容,还是用于计算等,都是全表扫描
DUAL
表,返回逻辑读一般为
3
个,无
FAST DUAL
SQL> set autotrace traceonly
SQL> select * from dual;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0
TABLE ACCESS (FULL) OF 'DUAL'
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
487 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select sysdate from dual;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'DUAL'
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
495 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
10g
则不同,如果只是利用
DUAL
表查找比如
SYSDATE,
做些相关计算,比如
1+1
,那么
Oracle
优化器
(
CBO,RBO
一样规则
)
采用
FAST DUAL
方式访问,它不需要真正访问
DUAL
表,因此逻辑读为
0
。
DINGJUN123>set autotrace traceonly
--
访问
DUAL
表本身的数据,不能走
FAST DUAL
,因为它需要真正访问表了
DINGJUN123>select * from dual
2 ;
已选择
1
行。
执行计划
----------------------------------------------------------
Plan hash value: 272002086
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
| 1 |
TABLE ACCESS FULL
| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
409 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
--
用于取系统函数,计算,启用
FAST DUAL,
不需要真正访问表,逻辑读为
0
DINGJUN123>select sysdate from dual;
已选择
1
行。
执行计划
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 |
FAST DUAL
| | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
417 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
--
这个也是访问了
DUAL
表
DINGJUN123>select dummy,sysdate from dual;
已选择
1
行。
执行计划
----------------------------------------------------------
Plan hash value: 272002086
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
| 1 |
TABLE ACCESS FULL|
DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
474 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
--RBO
虽然不用了,还是测试一下,规则与
CBO
一样
DINGJUN123>alter session set optimizer_mode=rule;
会话已更改。
DINGJUN123>select 1 from dual;
已选择
1
行。
执行计划
----------------------------------------------------------
Plan hash value: 1388734953
---------------------------------
| Id | Operation | Name |
---------------------------------
| 0 | SELECT STATEMENT | |
| 1 |
FAST DUAL
| |
---------------------------------
Note
-----
- rule based optimizer used (consider using cbo)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
406 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
DINGJUN123>select sysdate,sysdate,sysdate from dual;
已选择
1
行。
执行计划
----------------------------------------------------------
Plan hash value: 1388734953
---------------------------------
| Id | Operation | Name |
---------------------------------
| 0 | SELECT STATEMENT | |
| 1 |
FAST DUAL
| |
---------------------------------
Note
-----
- rule based optimizer used (consider using cbo)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
547 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
DINGJUN123>select dummy from dual;
已选择
1
行。
执行计划
----------------------------------------------------------
Plan hash value: 272002086
----------------------------------
| Id | Operation | Name |
----------------------------------
| 0 | SELECT STATEMENT | |
| 1 |
TABLE ACCESS FULL
| DUAL |
----------------------------------
Note
-----
- rule based optimizer used (consider using cbo)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
409 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
10g
有了
FAST DUAL
优化,增强了
DUAL
表作为常用工具的功能,这也是
Oracle10g
新版本带来的众多新特性之一,值得注意。