Cardinality基数 Selectivity选择性 Density 密度

------Cardinality用同一个词,但是意义不同的,

和Selectivity对应的是num_distinct=num_rows/density

和density对应的是预估SQL返回行数  retrived_rows=num_rows/num_distinct。 看第二段,可以知道这里翻译成 集合的势(根据单值查询返回的记录)更加好,不叫基数。

 Oracle在文档中,有时用基数来指一个操作返回的记录行数有时也将基数指不重复的值的数量,因此基数与选择性在《SQL优化核心思想》中也有如下解释:

这个基数用来考虑建index的

1、Cardinality(基数)某个列唯一键的数量(某列中不重复的值的数量,DISTINCT的数量),比如性别列,该列只有男女之分,所以这一列基数是2,基数越高与总行数越接近,数据分布可能会越均匀。

     CBO中Cardinality代表返回的行数,肯定是num_rows/num_distinct=Cardinality 是每个性能拥有的行数。

2、Selectivity(选择性)基数与总行数的比值再乘以100%,为某列的选择性(选择性大于20%,数据分布可能会越均衡)。
 

选择性大于20%,建索引就很高效。   下图转折点在20%附近,

这个和选择又不一样,在表里面用density 密度,这个是1/num_distinct

1000个行里面50个不同值,和100000个记录50个不同值他们的density是一样的,用density*num_rows=Cardinality 代表此字段单值的返回行数。

-----


      优化器(optimizer)是oracle数据库内置的一个核心子系统。优化器的目的是按照一定的判断原则来得到它认为的目标SQL在当前的情形下的最高效的执行路径,也就是为了得到目标SQL的最佳执行计划。依据所选择执行计划时所用的判断原则,oracle数据库里的优化器又分为RBO和CBO两种。

一、基于规则的优化器。《RBO: Rule-Based Optimization》

     Oracle会在代码里事先为各种类型的执行路径定一个等级,一共15个等级,从等级1到等级15,oracle认为等级1的执行路径是效率最高的,等级15是执行效率最差的。对于等级相同的执行计划,oracle根据目标对象的在数据字典中缓存的顺序判断选择哪一种执行计划。RBO是一种适合于OLTP类型SQL语句的优化器。相对于CBO而言,RBO有着先天的缺陷,一旦SQL语句的执行计划出现问题,将很难调整。因此,从ORACLE 10g开始,RBO已被CBO所取代。

    关于RBO的访问路径,官方文档做了详细介绍:

        RBO Path 1: Single Row by Rowid

RBO Path 2: Single Row by Cluster Join

RBO Path 3: Single Row by Hash Cluster Key with Unique or Primary Key

RBO Path 4: Single Row by Unique or Primary Key

RBO Path 5: Clustered Join

RBO Path 6: Hash Cluster Key

RBO Path 7: Indexed Cluster Key

RBO Path 8: Composite Index

RBO Path 9: Single-Column Indexes

RBO Path 10: Bounded Range Search on Indexed Columns

RBO Path 11: Unbounded Range Search on Indexed Columns

RBO Path 12: Sort Merge Join

RBO Path 13: MAX or MIN of Indexed Column

RBO Path 14: ORDER BY on Indexed Column

RBO Path 15: Full Table Scan

二、基于成本的优化器。《 CBO: Cost-Based Optimization》

       CBO是一种比RBO更加合理、可靠的优化器,它是从ORACLE 8中开始引入,但到ORACLE 9i 中才逐渐成熟,在ORACLE 10g中完全取代RBO。 CBO选择执行计划时,以目标SQL成本为判断原则,CBO会选择一条执行成本最小的执行计划作为SQL的执行计划,各条执行路径的成本通过目标SQL语句所涉及的表、索引、列等的统计信息算出。这里的成本是oracle通过相关对象的统计信息计算出来的一个值,它实际上代表目标SQL对应执行步骤所消耗的IO、CPU、网络资源(针对于dblink下的分布式数据库系统而言)的消耗量,oracle会把网络资源的消耗量计算在IO成本内,实际上你看到的成本为IO、CPU资源,另外需要注意的是,oracle在未引入系统统计信息之前,CBO所计算的成本值实际全是基于IO计算的。

1、Cardinality(基数,集的势)

      是Oracle预估的返回行数,即对目标SQL的某个具体执行步骤的执行结果所包含记录数的估算值。如果是针对整个目标SQL,那么此时的Cardinality就表示该SQL最终执行结果所包含记录数的估算值。例如,一张表T有1000行数据,列COL1上没有直方图,没有空值,并且不重复的值(Distinct Value)有500个。那么,在使用条件“WHERE COL1=”去访问表的时候,优化器会假设数据均匀分布,它估计出会有1000/500=2行被选出来,2就是这步操作的Cardinality。通常情况下,Cardinality越准确,生成的执行计划就会越高效。

2、Selectivity(可选择率)是指施加指定谓词条件后返回结果集的记录数占未施加任何谓词条件的原始结果集的记录数的比率。可选择率的取值范围显然是0~1,它的值越小,就表明可选择性越好。当可选择率为1时的可选择性是最差的。

 Selectivity=1  /   NUM_DISTINCT(目标列的DISTINCT的数量,此为最简单的计算可选择率的情况,在目标列上没有直方图,且没有NULL时的公式)

 Cardinality=NUM_ROWS   *   Selectivity

---------------------------------------------------------------------------------------------------------

2----------------------------------

集的势和选择性通常是在讨论查询计划时使用的两个术语。一个计划包含多个操作,其中包括一个输入的数据集和一个输出的数据集。集的势和选择性都是相对于输出结果集讨论的。

 

集的势

       在标准的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中有集的势提示。

       ·可以使用未文档化的集的势提示。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值