最近遇到了錯誤“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”,如下所示:
SQL> show user;
USER is "SYS"
SQL> SELECT *
2 FROM SCOTT.EMP3 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 307521 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,官方檔案介紹如下:
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.
如果沒有使用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時可能會遇到這種場景,
在SCOTT用戶下創建一個PLAN_TABLE(結構一樣,如果結構不一樣,會報另外一種錯誤)
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測驗,就會遇到這個錯誤,如下所示:
SQL> show user;
USER is "SYS"
SQL> alter session set current_schema=SCOTT;
Session altered.SQL> EXPLAIN PLAN FOR
2 SELECT * 3 FROM SCOTT.EMPWHERE 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_TABLESQL> 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-15PUBLIC PLAN_TABLE SYNONYM 30-JUN-05SCOTT PLAN_TABLE TABLE 21-DEC-19
如果遇到這種情況,可以使用上面腳本看看是否存在同名的PLAN_TABLE,這種情況下,可以將SCOTT下的PLAN_TABLE表重命名或洗掉即可,當然也可以用下面方法
SQL> EXPLAIN PLAN INTO SCOTT.PLAN_TABLE FOR
2 SELECT * 3 FROM SCOTT.EMPWHERE 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-ddhh24:mi:ss') AND "HIREDATE">=TO_DATE(' 1981-01-01 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))15 rows selected.SQL>
當然,還可以更深入的探究,只是沒有太多價值,而且個人在測驗程序中,發現還有許多其它狀況,例如解決了這個錯誤后,再去測驗,就發現不報錯,但是顯示的執行計劃還是原來SQL(不是當前SQL的執行計劃)......... ,當然也不排除還有一些場景可能遇到這個錯誤,這里僅僅描述了兩種場景,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/25103.html
標籤:Oracle
