最近遇到了错误“Error: cannot fetch last explain plan from PLAN_TABLE”,因而稍微研究了一下哪些场景下碰到这种错误,具体参考下面案例:数据库
1:忘记使用EXPLAIN PLAN放在SQL语句前面,而后使用使用SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)查看具体SQL的执行计划时,就会遇到错误“Error: cannot fetch last explain plan from PLAN_TABLE”。以下所示:session
SQL> show user;
USER is "SYS"
SQL> SELECT *
2 FROM SCOTT.EMP
3 WHERE HIREDATE BETWEEN '01-JAN-1981' AND '01-APR-1981';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
SQL> COL PLAN_TABLE_OUTPUT FOR A180;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
Error: cannot fetch last explain plan from PLAN_TABLE
其实,这种情形是由于SQL语句中忘记使用EXPLAIN PLAN,通常而言EXPLAIN PLAN会将SQL对应的执行计划放入plan_table。官方文档介绍以下:app
The EXPLAIN PLAN statement displays execution plans chosen by the Oracle optimizer for SELECT, UPDATE, INSERT, and DELETE statements. A statement's execution plan is the sequence of operations Oracle performs to run the statement. The row source tree is the core of the execution plan. ide
若是没有使用EXPLAIN PLAN,那么没有将对应SQL的执行计划放进PLAN_TABLE,而若是使用EXPLAIN PLAN,那么ORACLE会用格式化的数据填充PLAN_TABLE表,以便以易读的格式呈现给用户。我的使用10046跟踪对比了一下(对比使用EXPLAIN PLAN和不使用EXPLAIN PLAN两种状况),使用EXPLAIN PLAN时,数据库会向plan_table插入数据。以下所示:测试
2:对应的用户下存在PLAN_TABLE表(这个可能状况比较复杂),而后使用ALTER SESSION SET CURRENT_SCHEMA设置当前会话的SCHEMA时可能会遇到这种场景。fetch
在SCOTT用户下建立一个PLAN_TABLE(结构同样,若是结构不同,会报另一种错误)spa
SQL> SHOW USER;
USER is "SCOTT"
SQL>CREATE TABLE PLAN_TABLE AS
SELECT STATEMENT_ID,
PLAN_ID,
TIMESTAMP,
REMARKS,
OPERATION,
OPTIONS,
OBJECT_NODE,
OBJECT_OWNER,
OBJECT_NAME,
OBJECT_ALIAS,
OBJECT_INSTANCE,
OBJECT_TYPE,
OPTIMIZER,
SEARCH_COLUMNS,
ID,
PARENT_ID,
DEPTH,
POSITION,
COST,
CARDINALITY,
BYTES,
OTHER_TAG,
PARTITION_START,
PARTITION_STOP,
PARTITION_ID,
TO_LOB(OTHER) AS OTHER,
OTHER_XML AS OTHER_XML,
DISTRIBUTION,
CPU_COST,
IO_COST,
TEMP_SPACE,
ACCESS_PREDICATES,
FILTER_PREDICATES,
PROJECTION,
TIME,
QBLOCK_NAME
FROM PLAN_TABLE;
SQL> EXPLAIN PLAN FOR
2 SELECT * FROM DUAL;
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); #SCOTT用户下不会出错。
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------
8 rows selected.
SQL>
可是咱们使用ALTER SESSION SET CURRENT_SCHEMA设置当前会话的SCHEMA后,那么再按以前的SQL测试,就会遇到这个错误,以下所示:3d
SQL> show user;
USER is "SYS"
SQL> alter session set current_schema=SCOTT;
Session altered.
SQL> EXPLAIN PLAN FOR
2 SELECT *
3 FROM SCOTT.EMP
WHERE HIREDATE BETWEEN '01-JAN-1981' AND '01-APR-1981'; 4
Explained.
SQL> COL PLAN_TABLE_OUTPUT FOR A180;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Error: cannot fetch last explain plan from PLAN_TABLE
SQL> SET LINESIZE 1200
SQL> SELECT OWNER,OBJECT_NAME,OBJECT_TYPE,CREATED FROM ALL_OBJECTS
2 WHERE OBJECT_NAME LIKE 'PLAN_TABLE%'
3 AND OWNER IN (SYS_CONTEXT('USERENV','CURRENT_SCHEMA'),'PUBLIC','SYS');
OWNER OBJECT_NAME OBJECT_TYPE CREATED
------------------------------ ------------------------------ ------------------- ---------
SYS PLAN_TABLE$ TABLE 24-MAY-15
PUBLIC PLAN_TABLE SYNONYM 30-JUN-05
SCOTT PLAN_TABLE TABLE 21-DEC-19
若是遇到这种状况,可使用上面脚本看看是否存在同名的PLAN_TABLE,这种状况下,能够将SCOTT下的PLAN_TABLE表重命名或删除便可。固然也能够用下面方法code
SQL> EXPLAIN PLAN INTO SCOTT.PLAN_TABLE FOR
2 SELECT *
3 FROM SCOTT.EMP
WHERE HIREDATE BETWEEN '01-JAN-1981' AND '01-APR-1981';
Explained.
SQL> COL PLAN_TABLE_OUTPUT FOR A180;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP | 2 | 74 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------
1 - filter("HIREDATE"<=TO_DATE(' 1981-04-01 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "HIREDATE">=TO_DATE(' 1981-01-01 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))
15 rows selected.
SQL>
固然,还能够更深刻的探究,只是没有太多价值,并且我的在测试过程当中,发现还有许多其它情况,例如解决了这个错误后,再去测试,就发现不报错。可是显示的执行计划仍是原来SQL(不是当前SQL的执行计划)......... 。固然也不排除还有一些场景可能遇到这个错误。这里仅仅描述了两种场景。orm