添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

神奇的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 表记录数

神奇的DUAL表总结_oracle


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 新版本带来的众多新特性之一,值得注意。


2.2025-07-17:删除所有值为某个元素后的最大子数组和。用go语言,给定一个整数数组 nums,你可以进行以下操作最多一次: - 选择数组中某个整数 X。 - 删除数组中所有值为 X 的元素,但删 3.更换电脑同步pycharm配置 4.氧化锌避雷器破损缺陷检测数据集VOC+YOLO格式2408张1类别 5.工作中对InheritableThreadLocal使用的思考