ORACLE柱狀圖與執行計劃(轉)
一、不繫結變數的情況:
考慮以下資料
SQL> select owner,count(1) from th group by owner;
OWNER COUNT(1)
------------------------------ ----------
SUK 1
SYS 36216
SYSTEM 1
其中,在表的OWENR上建立有一個索引
做普通分析後,執行查詢
SQL> analyze table th compute statistics;
Table analyzed
suk@ORACLE9I> select * from th where owner='SYS';
已選擇36216行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=50 Card=12073 Bytes=
881329)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=50 Card=12073 Bytes=8813
29)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2894 consistent gets
0 physical reads
0 redo size
2045535 bytes sent via SQL*Net to client
27057 bytes received via SQL*Net from client
2416 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
36216 rows processed
suk@ORACLE9I> select * from th where owner='SUK';
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=50 Card=12073 Bytes=
881329)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=50 Card=12073 Bytes=8813
29)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
513 consistent gets
0 physical reads
0 redo size
1133 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
只需返回一條資料,但做了全表掃描,這是不合理的執行計劃。因為,它只是知道owner列有三個不同的值,但oracle不知道每個不同的owner分別有多少記錄,oracle預設為這些資料的分佈是完全均勻的,所以,當用owner作條件時,oracle會認為會返回總記錄的三分之一(從執行計劃中的Card=12073可以看出來)
對錶TH生成柱狀圖後在做同樣的查詢
SQL> analyze table th compute statistics for table for all indexes for all indexed columns;
Table analyzed
suk@ORACLE9I> select * from th where owner='SYS';
已選擇36216行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=50 Card=36216 Bytes=
2643768)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=50 Card=36216 Bytes=2643
768)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2894 consistent gets
0 physical reads
0 redo size
2045535 bytes sent via SQL*Net to client
27057 bytes received via SQL*Net from client
2416 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
36216 rows processed
suk@ORACLE9I> select * from th where owner='SUK';
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=73)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TH' (Cost=2 Card=1 Bytes
=73)
2 1 INDEX (RANGE SCAN) OF 'IDX_TH' (NON-UNIQUE) (Cost=1 Card
=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
1133 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
可見,生成了柱狀圖後,oracle會根據資料的實際分佈情況選擇合適的執行計劃,提高效能。
----------------------------------------------------------------------
二、繫結變數的情況下
下面看看在繫結變數的情況下,執行同樣的操作,會發生什麼事情
suk@ORACLE9I> analyze table th compute statistics;
表已分析。
suk@ORACLE9I> var o varchar2(20)suk@ORACLE9I> exec :o:='SYS'
PL/SQL 過程已成功完成。
suk@ORACLE9I> select * from th where owner=:o;
已選擇32192行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=75 Card=10731 Bytes=
783363)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=75 Card=10731 Bytes=7833
63)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2886 consistent gets
0 physical reads
0 redo size
1818406 bytes sent via SQL*Net to client
24109 bytes received via SQL*Net from client
2148 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
32192 rows processed
suk@ORACLE9I> exec :o:='SUK'
PL/SQL 過程已成功完成。
suk@ORACLE9I> select * from th where owner=:o;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=75 Card=10731 Bytes=
783363)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=75 Card=10731 Bytes=7833
63)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
770 consistent gets
0 physical reads
0 redo size
1151 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
從以上測試可以看到,在繫結變數的情況下,如果沒有分析柱狀圖,兩個查詢都使用了相同的執行計劃--全表掃描。這也很容易理解,在第一次解析SQL的時候,會根據:o的繫結的值去窺視表資料,因為oracle不知道連線列的資料的具體分佈,所以它會以為會返回三分之一的資料,所以選擇了全表掃描。在以後的執行同樣的SQL時會重用該SQL,都會使用第一次解析生成的執行計劃了。在本例中,由於沒有做柱狀圖,索引第一次執行select * from th where owner=:o時,無論:0是'SYS'還是'SUK',都會使用全表掃描。那麼,我們是否可以得出這樣的一個結論:如果對錶做了柱狀圖,那麼如果第一次硬解析SQL時:o的值是'SUK'時,這個sql將會使用索引掃描;如果第一次硬解析時:o的值是'SYS'時,SQL將會使用全表掃描呢?看如下的測試例子:
suk@ORACLE9I> alter system flush shared_pool;
系統已更改。
suk@ORACLE9I> analyze table th delete statistics;
表已分析。
suk@ORACLE9I> analyze table th compute statistics for table for all indexes for all indexed columns;
表已分析。
suk@ORACLE9I> exec :o:='SYS'
PL/SQL 過程已成功完成。
suk@ORACLE9I> select * from th where owner=:o;
已選擇32192行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=75 Card=10731 Bytes=
890673)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=75 Card=10731 Bytes=8906
73)
Statistics
----------------------------------------------------------
271 recursive calls
0 db block gets
2900 consistent gets
0 physical reads
0 redo size
1818406 bytes sent via SQL*Net to client
24109 bytes received via SQL*Net from client
2148 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
32192 rows processed
suk@ORACLE9I> alter system flush shared_pool;
系統已更改。
suk@ORACLE9I> exec :o:='SUK'
PL/SQL 過程已成功完成。
suk@ORACLE9I> select * from th where owner=:o;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=75 Card=10731 Bytes=
890673)
1 0 TABLE ACCESS (FULL) OF 'TH' (Cost=75 Card=10731 Bytes=8906
73)
Statistics
----------------------------------------------------------
529 recursive calls
0 db block gets
51 consistent gets
0 physical reads
0 redo size
1151 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
7 sorts (memory)
0 sorts (disk)
1 rows processed
從這個結果可以看到,分析了柱狀圖後,無論:o的值是'SYS'還是'SUK',第一次執行該sql時,使用的都是全表掃描,這與剛才我們的推論不一致了,如果真是這樣的話,使用繫結變數對錶做柱狀圖還有什麼意義呢?其實這應該算是ORACLE的一個BUG,在這裡AUTOTRACE的結果是不對的,我們可以用10046看
第一次執行
select *
from
th where owner=:o
當:o:='SYS'時
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.01 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2148 0.09 0.17 0 2886 0 32192
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2150 0.09 0.18 0 2886 0 32192
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 23
Rows Row Source Operation
------- ---------------------------------------------------
32192 TABLE ACCESS FULL TH
第一次執行
select *
from
th where owner=:o
當:o:='SUK'時
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.01 0 31 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 4 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.01 0 35 0 1
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 23
Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS BY INDEX ROWID TH
1 INDEX RANGE SCAN IDX_TH (object id 7248)
從9i開始,oracle在對sql第一次硬解析時,會對繫結的變數值進行窺視,從而根據變數值和資料的分佈決定sql的執行計劃。從以上的例子可以證明這點。
到此為止可以可以得出如下結論:
1、無論是否繫結變數,對資料分佈不均的情況下柱狀圖都是很有效的
2、對資料分佈不均勻的情況下,使用繫結變數可能會造成惡果,就算對錶做了柱狀圖也一樣
3、使用繫結變數,sql第一次執行決定了以後同樣的sql執行的執行計劃
4、AUTOTRACE的資訊不一定準確,必要時要用10046檢視需要的資訊
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7364032/viewspace-17470/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 柱狀圖與執行計劃
- oracle 柱狀圖(Histograms)OracleHistogram
- 簡單探討一下10G下柱狀圖和執行計劃
- 檢視oracle執行計劃 - 轉Oracle
- ORACLE中檢視執行計劃(轉)Oracle
- 柱狀圖
- Oracle9i 執行計劃(轉)Oracle
- 九、柱狀圖和3D柱狀圖3D
- ORACLE執行計劃Oracle
- Oracle直方圖 (柱狀圖 histograms) 詳解Oracle直方圖Histogram
- 怎樣看懂Oracle的執行計劃[轉]Oracle
- oracle 10g執行計劃 (轉帖)Oracle 10g
- oracle 固定執行計劃Oracle
- Oracle sql執行計劃OracleSQL
- oracle sqlprofile 固定執行計劃,並遷移執行計劃OracleSQL
- 分析執行計劃優化SQLORACLE的執行計劃(轉)優化SQLOracle
- echarts 柱狀圖 詳解與使用集合Echarts
- 【效能優化】執行計劃與直方圖優化直方圖
- oracle的執行計劃居然出錯[轉帖]Oracle
- 【執行計劃】Oracle獲取執行計劃的幾種方法Oracle
- 【Oracle】-【索引-HINT,執行計劃】-帶HINT的索引執行計劃Oracle索引
- PyQtGraph之柱狀圖QT
- 分析執行計劃最佳化SQLORACLE的執行計劃(轉)SQLOracle
- Oracle執行計劃詳解Oracle
- oracle固定執行計劃--sqlprofileOracleSQL
- Oracle 索引和執行計劃Oracle索引
- Oracle閱讀執行計劃Oracle
- oracle執行計劃相關Oracle
- oracle 執行計劃變更Oracle
- 【優化】Oracle 執行計劃優化Oracle
- oracle 執行計劃設定Oracle
- canvas圖表(1) - 柱狀圖Canvas
- toad與執行計劃
- 資料視覺化:圖表篇(1)—— 基本柱狀圖、堆疊柱狀圖視覺化
- javascript柱狀統計圖程式碼例項JavaScript
- JavaScript介面畫柱狀圖JavaScript
- Oracle-繫結執行計劃Oracle
- 【SPM】Oracle如何固定執行計劃Oracle