如何看懂ORACLE執行計畫
一、什麼是執行計畫
An explain plan is a representation of the access path that is taken when a query is executed within Oracle.
二、如何訪問資料
At the physical level Oracle reads blocks of data. The smallest amount of data read is a single Oracle block, the largest is constrained by operating system limits (and multiblock i/o). Logically Oracle finds the data to read by using the following methods:
Full Table Scan (FTS) --全表掃描
Index Lookup (unique & non-unique) --索引掃描(唯一和非唯一)
Rowid --物理行id
三、執行計畫層次關係
When looking at a plan, the rightmost (ie most inndented) uppermost operation is the first thing that is executed. --採用最右最上最先執行的原則看層次關係,在同一級如果某個動作沒有子ID就最先執行
1.一個簡單的例子:
SQL> select /*+parallel (e 4)*/ * from emp e;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=82 Bytes=7134)
1 0 TABLE ACCESS* (FULL) OF 'EMP' (Cost=1 Card=82 Bytes=7134):Q5000
--[:Q5000]表示是並行方式
1 PARALLEL_TO_SERIAL SELECT /*+ NO_EXPAND ROWID(A1) */ A1."EMPNO"
,A1."ENAME",A1."JOB",A1."MGR",A1."HI
最佳化模式是CHOOSE的情況下,看Cost參數是否有值來決定採用CBO還是RBO:
SELECT STATEMENT [CHOOSE] Cost=1234 --Cost有值,採用CBO
SELECT STATEMENT [CHOOSE] --Cost為空白,採用RBO(9I是如此顯示的)
2.層次的父子關係的例子:
PARENT1
**FIRST CHILD
****FIRST GRANDCHILD
**SECOND CHILD
Here the same principles apply, the FIRST GRANDCHILD is the initial operation then the FIRST CHILD followed by the SECOND CHILD and finally the PARENT collates the output.
四、例子解說
Execution Plan
----------------------------------------------------------
0 **SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=8 Bytes=248)
1 0 **HASH JOIN (Cost=3 Card=8 Bytes=248)
2 1 ****TABLE ACCESS (FULL) OF 'DEPT' (Cost=1 Card=3 Bytes=36)
3 1 ****TABLE ACCESS (FULL) OF 'EMP' (Cost=1 Card=16 Bytes=304)
左側的兩排資料,前面的是序號ID,後面的是對應的PID(父ID)。
A shortened summary of this is:
Execution starts with ID=0: SELECT STATEMENT but this is dependand on it's child objects
So it executes its first child step: ID=1 PID=0 HASH JOIN but this is dependand on it's child objects
So it executes its first child step: ID=2 PID=1 TABLE ACCESS (FULL) OF 'DEPT'
Then the second child step: ID=3 PID=2 TABLE ACCESS (FULL) OF 'EMP'
Rows are returned to the parent step(s) until finished
五、表訪問方式
1.Full Table Scan (FTS) 全表掃描
In a FTS operation, the whole table is read up to the high water mark (HWM). The HWM marks the last block in the table that has ever had data written to it. If you have deleted all the rows then you will still read up to the HWM. Truncate resets the HWM back to the start of the table. FTS uses multiblock i/o to read the blocks from disk. --全表掃描模式下會讀資料到表的高水位線(HWM即表示表曾經擴充的最後一個資料區塊),讀取速度依賴於Oracle初始化參數db_block_multiblock_read_count(我覺得應該這樣翻譯:FTS掃描會使表使用上升到高水位(HWM),HWM標識了表最後寫入資料的塊,如果你用DELETE刪除了所有的資料表仍然處於高水位(HWM),只有用TRUNCATE才能使表迴歸,FTS使用多IO從磁碟讀取資料區塊).
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
**INDEX UNIQUE SCAN EMP_I1 --如果索引裡就找到了所要的資料,就不會再去訪問表
2.Index Lookup 索引掃描
There are 5 methods of index lookup:
index unique scan --索引唯一掃描
Method for looking up a single key value via a unique index. always returns a single value, You must supply AT LEAST the leading column of the index to access data via the index.
eg:SQL> explain plan for select empno,ename from emp where empno=10;
index range scan --索引局部掃描
Index range scan is a method for accessing a range values of a particular column. AT LEAST the leading column of the index must be supplied to access data via the index. Can be used for range operations (e.g. > < <> >= <= between) .
eg:SQL> explain plan for select mgr from emp where mgr = 5;
index full scan --索引全域掃描
Full index scans are only available in the CBO as otherwise we are unable to determine whether a full scan would be a good idea or not. We choose an index Full Scan when we have statistics that indicate that it is going to be more efficient than a Full table scan and a sort. For example we may do a Full index scan when we do an unbounded scan of an index and want the data to be ordered in the index order.
eg: SQL> explain plan for select empno,ename from big_emp order by empno,ename;
index fast full scan --索引快速全域掃描,不帶order by情況下常發生
Scans all the block in the index, Rows are not returned in sorted order, Introduced in 7.3 and requires V733_PLANS_ENABLED=TRUE and CBO, may be hinted using INDEX_FFS hint, uses multiblock i/o, can be executed in parallel, can be used to access second column of concatenated indexes. This is because we are selecting all of the index.
eg: SQL> explain plan for select empno,ename from big_emp;
index skip scan --索引跳躍掃描,where條件列是非索引的前置列情況下常發生
Index skip scan finds rows even if the column is not the leading column of a concatenated index. It skips the first column(s) during the search.
eg:SQL> create index i_emp on emp(empno, ename);
SQL> select /*+ index_ss(emp i_emp)*/ job from emp where ename='SMITH';
3.Rowid 物理ID掃描
This is the quickest access method available.Oracle retrieves the specified block and extracts the rows it is interested in. --Rowid掃描是最快的訪問資料方式
六、表串連方式
七、運算子
1.sort --排序,很消耗資源
There are a number of different operations that promote sorts:
(1)order by clauses (2)group by (3)sort merge join –-這三個會產生排序運算
2.filter --過濾,如not in、min函數等容易產生
Has a number of different meanings, used to indicate partition elimination, may also indicate an actual filter step where one row source is filtering, another, functions such as min may introduce filter steps into query plans.
3.view --視圖,大都由內聯視圖產生(可能深入到視圖基表)
When a view cannot be merged into the main query you will often see a projection view operation. This indicates that the 'view' will be selected from directly as opposed to being broken down into joins on the base tables. A number of constructs make a view non mergeable. Inline views are also non mergeable.
eg: SQL>