新博客http://www.cnblogs.com/zhjh256 欢迎访问
分类: Oracle
2008-01-06 21:53:56
集的势和选择性通常是在讨论查询计划时使用的两个术语。一个计划包含多个操作,其中包括一个输入的数据集和一个输出的数据集。集的势和选择性都是相对于输出结果集讨论的。
集的势
在标准的PLAN_TABLE中有一列称为'Cardinality'。在上下文中,其意思是优化器估计在通过access/filter谓词后预计产生的行数。
例如,在一个表中有2000行数据,其中有一个row列,并且数据分布到5年,那么将假设精确的统计(ALL_TAB_COLUMNS 的NUM_DISTINCT, LOW_VALUE,HIGH_VALUE列)。当从这个表查询一年的数据时,PLAN_TABLE中的集的势(或者rows)将为400。
关键是假设精确的统计。但是有时候并不精确,在一个数据分布倾斜的情况下,直方图可能不够详细。也有在一些情况下,优化器所作的假设是无效的。
可以使用未文档化的集的势提示:
select /*+ CARDINALITY (t 10) */ * from table t;
该提示告诉优化器预计从t返回的行数为10行。
更为通常的是在提示可以用在子查询中,覆盖优化器自己估计返回的行数。需要注意的是该提示的意思是在计算输出大小时忽略输入数据集的大小。
该提示也可以使用连接集的势:
select /*+ CARDINALITY (t1 t2 t3 100) */ {columns}
from t1, t2, t3, t4 where ...
如下:
SQL> create table test_card as select to_char(sysdate,'yyyy') year,t.* from all_tables t where rownum<501;
Table created
SQL> select distinct year from test_card;
YEAR
----
2008
SQL> insert into test_card select * from test_card;
500 rows inserted
SQL> insert into test_card select * from test_card;
1000 rows inserted
SQL> commit;
Commit complete
SQL> update test_card set year=year-1 where rownum<1501;
1500 rows updated
SQL> commit;
Commit complete
SQL> update test_card set year=year-1 where rownum<1001;
1000 rows updated
SQL> update test_card set year=year-1 where rownum<11;
10 rows updated
SQL> commit;
Commit complete
SQL> select count(*) from test_card group by year;
COUNT(*)
----------
10
990
500
500
SQL> analyze table test_card COMPUTE STATISTICS;
Table analyzed
SQL> explain plan for
2 select * from test_card where year='2005';
Explained
SQL> @F:\oracle\RDBMS\ADMIN\utlxpls.sql;
Cannot SET MARKUP
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3916160364
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 500 | 87500 | 15 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST_CARD | 500 | 87500 | 15 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("YEAR"='2005')
13 rows selected
SQL> explain plan for
2 select /*+ CARDINALITY(t 10)*/* from test_card t where year='2005';
Explained
SQL> @F:\oracle\RDBMS\ADMIN\utlxpls.sql;
Cannot SET MARKUP
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3916160364
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 1750 | 15 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST_CARD | 10 | 1750 | 15 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("YEAR"='2005')
13 rows selected
选择性
选择性是指预计通过filter的行的比例,相对于一个直接数而言。如400/2000=0.2,0.2就是选择性。
不同于集的势在PLAN_TABLE中没有选择性列。但是,集的势是通过选择性和将在其上操作的行的行数计算出来的。因此在选择性0.2的1000行输入数据集上的集的势将为200。
也有一个未文档化的选择性提示:
select /*+SELECTIVITY (t 0.2) */ * from table t;
该提示将会告诉优化器只有20%的数据将返回,即使没有声明where子句。
通常在Oracle的估计不准确的情况下使用。
不同于集的势该提示考虑输入数据集的大小,并用来计算集的势。
但是,需要注意Metalink4121077:
·在10g中没有选择性提示,在10g和9.2中有集的势提示。
·可以使用未文档化的集的势提示。