【sql調優之執行計劃】estimator i
Oracle的estimator(評估器)產生3種不同型別的評估量:
Selectivity選擇性
Cardinality集勢
Cost開銷
這些評估量互相之間是關聯的,estimator的目的是評估plan的整體cost,如果統計資訊是可用的,estimator將使用統計資訊來計算評估量。
Selectivity
選擇性是指從行集中返回的行的比例,行集可以是基本表,檢視,或者是由join或者group by等操作產生的結果集。Selectivity取決於查詢謂詞(predicate)或者查詢謂詞的組合。謂詞的選擇性表明了限定謂詞後返回多少行。選擇性的取值範圍是0到1,選擇性為0意味著沒有從行集中選擇行,為1則意味著選擇了所有行。
當統計資訊可用的時候estimator使用它來評估選擇性,比如一個相等謂詞(equality predicate)ename=’Smith’,選擇性就為1/distinct(ename),如果ename上有可用的直方圖,那麼評估器使用直方圖來計算選擇性,而不是用distinct value。直方圖記錄了列上不同值的分佈,所以將較好的評價選擇性,這個很好理解。
Cardinality
集勢表示行集的行數,同樣這裡的行集可以是基本表,檢視,或者join,group by等操作的結果集。
Base cardinality是指基本表的行數,可以通過analyze table來獲得,如果表統計資訊不可用,estimator將使用table的extents數來評估base cardinality。
Effective cardinality是指從表中選擇的行,如果基礎表上沒有謂詞,那麼它就等於表的Base cardinality
例子:
SQL> explain plan for
2 select * from dual;
已解釋。
SQL> select * from dual;
D
-
X
執行計劃
----------------------------------------------------------
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 |
--------------------------------------------------------------------------
SQL> select a.operation,a.cardinality,a.cost from plan_table a;
OPERATION CARDINALITY COST
------------------------------ ----------- ----------
SELECT STATEMENT 1 2
TABLE ACCESS 1 2
再看一個例子:
SQL> explain plan for
2 select a.empno,a.ename from scott.emp a where a.deptno < 20 ;
已解釋。
SQL> select a.empno,a.ename from scott.emp a where a.deptno < 20 ;
EMPNO ENAME
---------- ----------
7782 CLARK
7839 KING
7934 MILLER
執行計劃
----------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 52 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP | 4 | 52 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("A"."DEPTNO"<20)
..
SQL> select a.operation,a.cardinality,a.cost from plan_table a;
OPERATION CARDINALITY COST
------------------------------ ----------- ----------
SELECT STATEMENT 4 3
TABLE ACCESS 4 3
可以看到這裡的cardinality並不是期待的3,如果返回的行為0(比如使用<10,rownum<1等條件),cardinality也是1,就這個例子而言,使用<的條件始終比行數要多1,而=,>=,<=則與返回的行數一致。
事實上這種情況(全表掃描)的cardinality可以這樣計算:num_rows*表的選擇性=15*(1/20+1/3)=5.75
其中對於非索引欄位,,>=,<=,<>,not in等的選擇性=(1/20+1/欄位唯一值數)
而=的選擇性=(1/100+1/欄位唯一值數)
對於索引欄位的選擇性,=的選擇性是1/欄位唯一值數
而其他的則是(1/欄位唯一值數+1/記錄數)
不一一累述。
Join cardinality是join後產生的行數,是兩個行集的cardinality的乘積,然後乘以連線謂詞的選擇性的結果。看個例子
笛卡爾乘積,很顯然笛卡爾乘積沒有連線條件,選擇性為1,選擇所有join後的結果
則:
SQL> explain plan for
2 select a.empno,a.ename,a.* from scott.emp a,scott.dept b ;
已解釋。
SQL> select a.operation,a.cardinality,a.cost from plan_table a;
OPERATION CARDINALITY COST
------------------------------ ----------- ----------
SELECT STATEMENT 60 7
MERGE JOIN 60 7
INDEX 4 1
BUFFER 15 6
TABLE ACCESS 15 2
Cardinality為兩者的cardinality的乘積4*15=60
修改一下上述查詢,增加條件:
SQL> explain plan for
2 select a.empno,a.ename,b.dname from scott.emp a,scott.dept b
3 where a.deptno = b.deptno
4 and a.sal < 2000
5 ;
已解釋。
SQL> select a.operation,a.cardinality,a.cost from plan_table a;
OPERATION CARDINALITY COST
------------------------------ ----------- ----------
SELECT STATEMENT 6 4
NESTED LOOPS 6 4
TABLE ACCESS 6 3
TABLE ACCESS 1 1
INDEX 1 0
增加了a.sal<2000以後,看看這時候的cardinality是如何計算的:
SQL> select count(*) from scott.emp a ;
COUNT(*)
----------
15
SQL> select count(*) from scott.dept a ;
COUNT(*)
----------
4
SQL> select count(*) from scott.emp a where a.sal < 2000 ;
COUNT(*)
----------
9
SQL> select count(*) from scott.dept a where a.deptno in
2 (select a.deptno from scott.emp a where a.sal < 2000 )
3 ;
COUNT(*)
----------
3
看看具體的執行計劃:
SQL> select a.empno,a.ename,b.dname from scott.emp a,scott.dept b
2 where a.deptno = b.deptno
3 and a.sal < 2000
4 ;
執行計劃
----------------------------------------------------------
Plan hash value: 351108634
--------------------------------------------------------------------------------
--------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Ti
me |
--------------------------------------------------------------------------------
--------
| 0 | SELECT STATEMENT | | 6 | 156 | 4 (0)| 00
:00:01 |
| 1 | NESTED LOOPS | | 6 | 156 | 4 (0)| 00
:00:01 |
|* 2 | TABLE ACCESS FULL | EMP | 6 | 78 | 3 (0)| 00
:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | 1 (0)| 00
:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00
:00:01 |
--------------------------------------------------------------------------------
--------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("A"."SAL"<2000)
4 - access("A"."DEPTNO"="B"."DEPTNO")
上面這些數值按照之前描述的演算法計算,兩個行集的cardinality乘積乘以join謂詞的選擇性:
對於nested loops join,hash join ,sort merge join來說選擇性可以有這樣的計算公式:
Join Selectivity =
((num_rows(t1) - num_nulls(t1.c1)) / num_rows(t1)) *
((num_rows(t2) - num_nulls(t2.c2)) / num_rows(t2)) /
greater(num_distinct(t1.c1), num_distinct(t2.c2))
即 9*3*((15-0)/15*(4-0)/4/greatest(3,4))
而cardinality= Join Selectivity *filtered cardinality(t1) * filtered cardinality(t2)
故而可以計算出cardinality:
SQL> Select 9*3*((15-0)/15*(4-0)/4/greatest(3,4)) from dual;
9*3*((15-0)/15*(4-0)/4/GREATEST(3,4))
-------------------------------------
6.75
Distinct cardinality
是行集中某一列的distinct值
Group cardinality
是一個行集在應用了group by操作後產生的行數
9i文件中描述如下:
group cardinality lies between max ( dist. card. colx , dist. card. coly )
and min ( (dist. card. colx * dist. card. coly) ,
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16179598/viewspace-671532/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【sql調優之執行計劃】獲取執行計劃SQL
- 【sql調優之執行計劃】sort operationsSQL
- 【sql調優之執行計劃】hash joinSQL
- 【sql調優之執行計劃】query transformerSQLORM
- 【sql調優之執行計劃】temp table transformationSQLORM
- 【sql調優之執行計劃】in相關的operationSQL
- 【sql調優之執行計劃】merge sort joinSQL
- 【sql調優之執行計劃】使用hint(五)Hint for parallelSQLParallel
- 【sql調優之執行計劃】使用hint(四)Hints for JoinSQL
- mysql調優之——執行計劃explainMySqlAI
- 【sql調優之執行計劃】使用hint(三)Hints for Query TransformationsSQLORM
- 【sql調優之執行計劃】使用hint(二)Hints for Access PathsSQL
- Oracle調優之看懂Oracle執行計劃Oracle
- 【sql調優之執行計劃】使用hint(六) append and noappendSQLAPP
- 【sql調優之執行計劃】merge join cartesian and buffer sortSQL
- 【sql調優之執行計劃】使用hint(一)Hints for Optimization Approaches and GoalsSQLAPPGo
- 【sql調優之執行計劃】merge semi join and merge anti joinSQL
- 【sql調優之執行計劃】nested loops join and nested loop join outerSQLOOP
- 建立索引調整sql的執行計劃索引SQL
- oracle筆記整理14——效能調優之oracle執行計劃Oracle筆記
- Oracle中SQL調優(SQL TUNING)之最權威獲取SQL執行計劃大全OracleSQL
- 控制執行計劃之-SQL Profile(一)SQL
- sql 執行計劃SQL
- Oracle+高效能SQL引擎剖析:SQL優化與調優機制詳解-筆記之執行計劃(一)OracleSQL優化筆記
- Oracle+高效能SQL引擎剖析:SQL優化與調優機制詳解-筆記之執行計劃(二)OracleSQL優化筆記
- ORACLE SQL調優之執行計劃與隱藏引數_complex_view_mergingOracleSQLView
- 使用leading(,)優化sql執行計劃優化SQL
- MySQL調優篇 | EXPLAIN執行計劃解讀(4)MySqlAI
- Oracle sql執行計劃OracleSQL
- SQL Server執行計劃SQLServer
- SQL的執行計劃SQL
- SQL執行計劃分析SQL
- oracle 9i 獲取sql執行計劃(書寫長的sql)OracleSQL
- SQL優化案例-從執行計劃定位SQL問題(三)SQL優化
- 分析執行計劃優化SQLORACLE的執行計劃(轉)優化SQLOracle
- 效能調優:看看這個匪夷所思的執行計劃。
- Oracle9i 執行計劃(轉)Oracle
- 獲取SQL執行計劃SQL