FAST DUAL执行计划是Oracle10g的新特性。对于利用DUAL进行的计算,可以不用真正的访问表,从而快速的得到结果。
这个改变似乎并不起眼,但是累计起来对于系统的影响就是很大的。
下面看一个实际系统中的例子,由于中间件采用了WEBLOGIC,中间件为了确保
数据库连接没有
问题,需要在每个SQL前面执行一个SELECT 1 FROM DUAL语句,通过这个执行过程来检测
数据库连接是否正常。
如果不设置连接检查,那么一旦网络出现故障,可能导致这个连接后面所有的SQL运行出错。
虽然只是一个SELECT 1 FROM DUAL语句,但是由于执行次数众多,在V$SQL中已经可以看到执行次数和BUFFER_GETS:
SQL> SELECT EXECUTIONS, BUFFER_GETS FROM V$SQL WHERE SQL_TEXT = 'SELECT 1 FROM DUAL';
EXECUTIONS BUFFER_GETS
---------- -----------
27674608 83025056
1 row selected.
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Solaris: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production
虽然一次DUAL表的访问一般只有3个逻辑读,但是积少成多。在另一个产品库中,居然发生了溢出:
SQL> SELECT EXECUTIONS, BUFFER_GETS FROM V$SQL WHERE SQL_TEXT = 'SELECT 1 FROM DUAL';
EXECUTIONS BUFFER_GETS
---------- -----------
743695660 -2.064E+09
关于BUFFER_GETS溢出的描述可以参考:
http://yangtingkun.itpub.net/post/468/385990最后来看看10g的产品库:
SQL> SELECT EXECUTIONS, BUFFER_GETS FROM V$SQL WHERE SQL_TEXT = 'SELECT 1 FROM DUAL';
EXECUTIONS BUFFER_GETS
---------- -----------
48321325 110
将近5千万次执行,而BUFFER_GETS才110。这就是10g的新特性FAST DUAL的功劳。
SQL> SET AUTOT ON
SQL> SELECT 1 FROM DUAL;
1
----------
1
已选择 1 行。
执行计划
----------------------------------------------------------
Plan hash value: 1546270724
-----------------------------------------------------------------
| 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 |
-----------------------------------------------------------------
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
509 bytes sent via SQL*Net to client
492 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 * FROM DUAL;
D
-
X
已选择 1 行。
执行计划
----------------------------------------------------------
Plan hash value: 3543395131
--------------------------------------------------------------------------
| 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 |
--------------------------------------------------------------------------
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
512 bytes sent via SQL*Net to client
492 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
如果是用DUAL表进行计算,而不是从中取出记录的话,Oracle采用了FAST DUAL执行计划,而没有真正访问表,因此逻辑读为0;对比SELECT * FROM DUAL,由于Oracle仍然要访问DUAL表才能取出其中的内容,因此仍然需要三个逻辑读。