很多时候我们总是喜欢使用set autotrace on、set autotrace traceonly和set autotrace traceonly explain这种方式来查看目标SQL的执行计划,但是你知道吗?autotrace方式查看执行计划,如果目标SQL是DML语句会被实际执行。
先测试select
SQL> select SQL_TEXT,EXECUTIONS from v$sqlarea where sql_text like 'select * from test where id=1';
SQL_TEXT EXECUTIONS
------------------------------------------------------------ ----------
select * from test where id=1 1
SQL> set autotrace traceonly explain
SQL> select * from test where id=1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 142 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST | 1 | 142 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL> set autotrace off
SQL> select SQL_TEXT,EXECUTIONS from v$sqlarea where sql_text like 'select * from test where id=1';
SQL_TEXT EXECUTIONS
------------------------------------------------------------ ----------
select * from test where id=1 1
通过上述,可以证明在 set autotrace 语句执行select不会实际执行。
我们在来看下当使用set autorace on时,执行DML语句会怎么样?
SQL> select * from test;
ID NAME
---------- ------------------------------
1 zhang
2 wang
SQL> set autotrace on
SQL> delete from test where id=1;
1 row deleted.
Execution Plan
----------------------------------------------------------
Plan hash value: 180605370
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 13 | 3 (0)| 00:00:01 |
| 1 | DELETE | TEST | | | | |
|* 2 | TABLE ACCESS FULL| TEST | 1 | 13 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
3 db block gets
7 consistent gets
0 physical reads
0 redo size
682 bytes sent via SQL*Net to client
599 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> set autotrace off
SQL> select * from test;
ID NAME
---------- ------------------------------
2 wang
可以看出,DML语句已经被实际执行。
继续接着上述实验,我们看下set autotrace traceonly时,执行insert会怎么样?
SQL> set autotrace traceonly
SQL> insert into test values('1','zhang');
1 row created.
Execution Plan
----------------------------------------------------------
--------------------------------------------------------------------------------
-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
-
| 0 | INSERT STATEMENT | | 1 | 100 | 1 (0)| 00:00:01
|
| 1 | LOAD TABLE CONVENTIONAL | TEST | | | |
|
--------------------------------------------------------------------------------
-
Statistics
----------------------------------------------------------
0 recursive calls
3 db block gets
1 consistent gets
0 physical reads
300 redo size
682 bytes sent via SQL*Net to client
608 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> set autotrace off
SQL> select * from test;
ID NAME
---------- ------------------------------
1 zhang
2 wang
同样也可以看到insert语句也被实际执行了。
我们再来验证下set autotrace traconly explain查看DML语句的执行计划是否会被实际执行:
SQL> select SQL_TEXT,EXECUTIONS from v$sqlarea where sql_text like 'delete from test where id=1';
SQL_TEXT EXECUTIONS
------------------------------------------------------------ ----------
delete from test where id=1 0
SQL> set autotrace traceonly explain
SQL> delete from test where id=1;
1 row deleted. --注意此处提示
Execution Plan
----------------------------------------------------------
Plan hash value: 180605370
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 13 | 3 (0)| 00:00:01 |
| 1 | DELETE | TEST | | | | |
|* 2 | TABLE ACCESS FULL| TEST | 1 | 13 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
--可以看出数据已经被删除
SQL> select * from test where id=1;
no rows selected
SQL> select SQL_TEXT,EXECUTIONS from v$sqlarea where sql_text like 'delete from test where id=1';
SQL_TEXT EXECUTIONS
------------------------------------------------------------ ----------
delete from test where id=1 1
同样我们可以看到DML语句已被实际执行。
从上述的例子我们可以看出使用set autotrace后执行DML语句,该DML会被实际执行。所以在使用set autotrace来获取DML语句的执行计划时要特别小心,因为这些DML会被实际执行。