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/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16179598/viewspace-671532/