ITPub博客

首页 > 数据库 > Oracle > cbo心得(选择率,基数,直方图)(一)

cbo心得(选择率,基数,直方图)(一)

原创 Oracle 作者:sunwgneuqsoft 时间:2008-03-05 10:57:34 0 删除 编辑

一,概述

关于CBO优化器你上网可以搜到一大堆的介绍。用一句话来解释CBOCBO是一种根据执行代价来选择执行计划的机制。对于CBO来说,最重要的就是各种不同的执行计划的代价的计算。和RBO比较起来,CBO确实要聪明很多。CBO会根据对象上的统计信息来进行执行计划的代价评估,选择出较为高效的。而不是象RBO那样根据一些既有的规则来选择执行计划,愣头青一样的。

[@more@]

既然是根据对象上的统计信息来计算代价,那么统计信息对于CBO的重要性就不用多说了。所以在CBO的数据库上,统计信息一定要定期收集,保证不光要有统计信息,而且也要尽量保证统计信息的准确性。不准确的统计信息可能比没有统计信息还要糟糕。

最近一直在看关于CBO的东西,有了一些简单的体会,拿出来分享一下,对我自己来说也是一个再提高的过程。

下面主要就是对CBO中几个最基本的概念的说明。它们主要是:选择率,基数和直方图。

二,基础知识

选择率:目标结果集占全部数据的百分比

基数:目标结果集的大小

直方图:列上的统计信息,主要用于倾斜度很高的列上

选择率和基数的含义差不多太多,都是为了描述目标结果集的大小的。选择率和基数是CBO的基础,在选择SQL执行计划的主要参考的就是这两个结果。比如说:

Create table sunwg as select * from dba_objects;

Create index ind_sunwg_1 on sunwg(object_id);

Create index ind_sunwg_2 on sunwg(owner);

对于查询select * from sunwg where object_id = 12345来说,是选择索引扫描还是选择全表扫描呢?答案很简单,哪个效率更好就选择哪个。CBO会根据表和列上的统计信息得知这个查询大概会返回1行记录,在5W多条记录中选择一条,那么基数就是1,使用索引的效果会更好,这样大概几个IO就可以搞定。

对于查询select * from sunwg where owner = ‘SYS’来说,这个查询会返回几W条记录,那么自然而然就会想到全表扫描会更加的快。

所以说选择率和基数对于执行计划的选择起着相当重要的影响。

直方图也是列上统计信息的一种。我们常用的统计信息主要包括表上的统计信息,索引上的统计信息,在有就是列上的统计信息了。

查看表上的统计信息

SQL> select NUM_ROWS, --表中的记录数

BLOCKS, --表中数据所占的数据块数

EMPTY_BLOCKS, --表中的空块数

AVG_SPACE, --数据块中平均的使用空间

CHAIN_CNT, --表中行连接和行迁移的数量

AVG_ROW_LEN --每条记录的平均长度

from user_tables

where table_name = 'SUNWG';

NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE AVG_ROW_LEN

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

5050 12 3 3450 6

从上面的结果可以看到表SUNWG一共有5050条记录,占用了15个数据块,其中有12块是存储数据的,另外3个数据块是空的,平均每个块使用3450B的空间,平均每条记录的长度是6B

查看索引的统计也是类似的

select BLEVEL, --索引的层数

LEAF_BLOCKS, --叶子结点的个数

DISTINCT_KEYS, --唯一值的个数

AVG_LEAF_BLOCKS_PER_KEY, --每个KEY的平均叶块个数

AVG_DATA_BLOCKS_PER_KEY, --每个KEY的平均数据块个数

CLUSTERING_FACTOR --群集因子

from user_indexes

where index_name = ‘IND_SUNWG_1;

查看列上的统计信息

select NUM_DISTINCT, --唯一值的个数

LOW_VALUE, --列上的最小值

HIGH_VALUE, --列上的最大值

DENSITY, --选择率因子(密度)

NUM_NULLS, --空值的个数

NUM_BUCKETS, --直方图的BUCKET个数

HISTOGRAM --直方图的类型

from user_tab_columns

where table_name ='SUNWG'

and column_name = 'OBJECT_ID';

查询列上的直方图信息

select ENDPOINT_NUMBER,

ENDPOINT_VALUE

from user_tab_histograms

where table_name ='SUNWG'

and column_name = 'OBJECT_ID';

上面的这几个查询就是我们工作中经常会遇到的关于统计信息的查询。为什么要统计表,索引和列的统计信息比较好理解,关于直方图信息可能很多人都是比较模糊,不知道为什么要统计直方图,直方图到底有什么用。下面用个例子来说明:
drop table sunwg purge;

Create table sunwg (id number);

Create index ind_sunwg on sunwg(id);

Insert into sunwg select 1 from dba_objects where rownum < 5000;

Insert into sunwg select rownum from dba_objects where rownum < 5002;

Commit;

对于查询select * from sunwg where id = 1来说,表中一共有1W条记录,而id = 1的记录有5000条,占了50%,在这种情况下,走全表扫描来说是更明智的。对于查询select * from sunwg where id = 500来说,表中一共有1W条记录,而id = 1的记录只有1条,这时候应该走索引扫描更好。这是我们知道数据分布的情况下。

假设现在我们没有收集列ID上的直方图信息,我们仅仅有表上的,索引上的和列上的统计信息。我们能得到的统计信息大概是这样的,表上一共有1W条记录,其中大概有5001个不同的值,ID最小的值是1ID最大的值是5001。在表中ID的值是平均分布的情况下,我们可以得到选择率大概是1/5001,走索引扫描会快一些。那么对于前面说的id = 1id = 5000的查询,CBO会选择执行索引的扫描。前面我们已经分析了,对于id = 1来说最好的方式就是全表扫描,此时CBO选择了不合适的执行计划。这也不能怪CBO,因为我们给它的信息并不完整,不足以分析出ID上的这些差异。直方图就是为了解决这样的问题。

直方图对于那些列上值分布不平均,列上信息明显倾斜的列十分的有用。有了列上的直方图信息后,CBO就可以知道大概的数据分布,就可以作出相对来说更加正确的选择。至于CBO是如果使用直方图信息的,我们在下面会详细的介绍。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8394333/viewspace-1000430/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    56
  • 访问量
    758636