如何看懂oracle 直方图

转自:http://czmmiao.iteye.com/blog/1484298

直方图概述:
在Oracle中直方图是一种对数据分布质量情况进行描述的工具。它会按照某一列不同值出现数量多少,以及出现的频率高低来绘制数据的分布情况,以便能够指导优化器根据数据的分布做出正确的选择。

在某些情况下,表的列中的数值分布将会影响优化器使用索引还是执行全表扫描的决策。当where 子句的值具有不成比例数量的数值时,将出现这种情况,使得全表扫描比索引访问的成本更低。这种情况下如果where 子句的过滤谓词列之上有一个合理的正确的直方图,将会对优化器做出正确的选择发挥巨大的作用,使得SQL语句执行成本最低从而提升性能。
在分析表或索引时,直方图用于记录数据的分布。通过获得该信息,基于成本的优化器就可以决定使用将返回少量行的索引,而避免使用基于限制条件返回许多行的索引。直方图的使用不受索引的限制,可以在表的任何列上构建直方图。
构造直方图最主要的原因就是帮助优化器在表中数据严重偏斜时做出更好的规划 。例如,如果一到两个值构成了表中的大部分数据(数据偏斜),相关的索引就可能无法帮助减少满足查询所需的I/O数量。创建直方图可以让基于成本的优化器知道何时使用索引才最合适,或何时应该根据WHERE子句中的值返回表中80%的记录。

通常情况下在以下场合中建议使用直方图:
1、当Where子句引用了列值分布存在明显偏差的列时:当这种偏差相当明显时,以至于WHERE 子句中的值将会使优化器选择不同的执行计划。这时应该使用直方图来帮助优化器来修正执行路径。(注意:如果查询不引用该列,则创建直方图没有意义。这种错误很常见,许多 DBA 会在偏差列上创建柱状图,即使没有任何查询引用该列。)
2、当列值导致不正确的判断时:这种情况通常会发生在多表连接时,例如,假设我们有一个五项的表联接,其结果集只有10行。Oracle 将会以一种使第一个联接的结果集(集合基数)尽可能小的方式将表联接起来。通过在中间结果集中携带更少的负载,查询将会运行得更快。为了使中间结果最小化,优化器尝试在SQL执行的分析阶段评估每个结果集的集合基数。在偏差的列上拥有直方图将会极大地帮助优化器作出正确的决策。如优化器对中间结果集的大小作出不正确的判断,它可能会选择一种未达到最优化的表联接方法。因此向该列添加直方图经常会向优化器提供使用最佳联接方法所需的信息。
等频直方图与等高直方图
默认的,如果一个倾斜列上的唯一值超过了254个,那么ORACLE会对此列建立等高直方图,否则建立等频直方图。我们先来看下等频直方图。
所谓的等频即按照列上的不同数据值进行划分,由于每个数值的频度相同,高度不同,故称为等频。下面是具体例子:
通过如下方式,建立表TAB,更新字段B,让列B产生倾斜。并在B列上创建索引。

SQL> create table tab(a number,b number);

Table created.
SQL> insert into tab select rownum,rownum from dual connect by level <=10000;

10000 rows created.

SQL> commit;

Commit complete.

SQL> update tab set b=5 where b between 6 and 9995;

9990 rows updated.

SQL> commit;

Commit complete.

SQL> create index tab_b_idx on tab(b);

Index created.
然后分析表,强制使列B不产生直方图。
SQL> exec dbms_stats.gather_table_stats('HR','TAB',cascade=>true,method_opt=>'FOR COLUMNS B SIZE 1');

PL/SQL procedure successfully completed.
查看视图USER_TAB_HISTOGRAMS 或者DBA_TAB_COL_STATISTICS 
SQL> select TABLE_NAME,COLUMN_NAME,ENDPOINT_NUMBER,ENDPOINT_VALUE from user_histograms where TABLE_NAME='TAB'

TABLE_NAME   COLUMN_NAME  ENDPOINT_NUMBER ENDPOINT_VALUE
------------ ------------ --------------- --------------
TAB          B                          0              1
TAB          B                          1          10000
列B上只有最大值,最小值两条记录分别对应端点号(endpoint_number)0和1,这种显示说明列B没有直方图信息。 

在没有直方图的情况下,在B列上进行等值查询的时候,都是索引范围扫描。
SQL>  select * from tab where b=5

Execution Plan
----------------------------------------------------------
Plan hash value: 157166354

-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |  1000 |  6000 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB       |  1000 |  6000 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | TAB_B_IDX |  1000 |       |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("B"=5)
收集直方图信息。看看是什么效果。由于列B唯一值的个数没有超过254因此产生的是等频直方图。
SQL> exec dbms_stats.gather_table_stats('HR','TAB',cascade=>true);

PL/SQL procedure successfully completed.
默认是对所有列分析直方图

在B=1时候采用索引扫描,而B=5时候,已经采用全表扫描了,说明直方图起了作用。
SQL> select * from tab where b=1;

Execution Plan
----------------------------------------------------------
Plan hash value: 157166354

-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |     1 |     6 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB       |     1 |     6 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | TAB_B_IDX |     1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("B"=1) 
SQL>
select * from tab where  b=5;

Execution Plan
----------------------------------------------------------
Plan hash value: 1995730731

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  9991 | 59946 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TAB  |  9991 | 59946 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("B"=5)

 

查看此时的直方图信息:

SQL> select TABLE_NAME,COLUMN_NAME,ENDPOINT_NUMBER,ENDPOINT_VALUE from user_histograms where table_name='TAB';

TABLE_NAME   COLUMN_NAME  ENDPOINT_NUMBER ENDPOINT_VALUE
------------ ------------ --------------- --------------
TAB          B                          1              1
TAB          B                          2              2
TAB          B                          3              3
TAB          B                          4              4
TAB          B                       9995              5
TAB          B                       9996           9996
TAB          B                       9997           9997
TAB          B                       9998           9998
TAB          B                       9999           9999
TAB          B                      10000          10000
TAB          A                          0              1

TABLE_NAME   COLUMN_NAME  ENDPOINT_NUMBER ENDPOINT_VALUE
------------ ------------ --------------- --------------
TAB          A                          1          10000

12 rows selected.

其中EDNPOINT_NUMBER是累计值。EDNPOINT_VALUE是列的值。可以看出这种等频直方图统计的列的信息是非常精确的。它为每一个列值分配了一个bucket。从执行计划的ROWS部分也可以看出ORACLE计算出来的cardinality是9991,和实际的情况完全吻合。
如果想知道每一个列值对应的数量是多少,需要做一下简单的减法运算:假如想知道列值等于5的个数,那么可以通过:9995-4=9991得到。这就是ENDPOINT_NUMBER累计值的含义。

以上部分,就是如何看懂直方图的办法,如果能够理解这些,直方图就能看懂了。

等高直方图,当列上的数据不同值超过254时,Oracle将会默认将列上的数据划分为高度一致但频度不一致的等高直方图。
SQL> exec dbms_stats.gather_table_stats('HR','TAB',cascade=>true,method_opt=>'FOR COLUMNS B SIZE 8);

PL/SQL procedure successfully completed.
由于列B有10个唯一值,通过上面的size 8可以强制ORACLE使用等高直方图。
查看直方图信息.
SQL> select TABLE_NAME,COLUMN_NAME,ENDPOINT_NUMBER,ENDPOINT_VALUE from user_histograms where table_name='TAB';

TABLE_NAME   COLUMN_NAME  ENDPOINT_NUMBER ENDPOINT_VALUE
------------ ------------ --------------- --------------
TAB          B                          0              1
TAB          B                          7              5
TAB          B                          8          10000
TAB          A                          0              1
TAB          A                          1          10000

从查询结果惊奇的发现只有三个桶0 7 8,原来ORACLE会自动省去EDNPOINT_VALUE值相同且ENDPOINT_NUMBER相邻的桶的值。省去了桶(EDNPOINT_NUMBER)为1 2 3 4 5 6 ,EDNPOINT_VALUE为5的六条内容。
说明:在等高直方图中,EDNPOINT_NUMBER代表桶号,这一点与等频直方图不同。再看等高直方图下的执行计划: 
SQL>  select * from tab where b=5

Execution Plan
----------------------------------------------------------
Plan hash value: 1995730731

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  9982 | 59892 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TAB  |  9982 | 59892 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("B"=5)
有执行计划的ROWS部分,ORACLE计算出来的cardinality不是特别精确的。9991才是精确值。而等频直方图可以精确到9991,因此可以说等频直方图比等高直方图稳定,精确。
可是现实很多时候,列的唯一值是超过254的。只能使用等高直方图了。
一个注意点(删除直方图)
如果需要删除直方图信息,10g中可以通过上面提到的
exec dbms_stats.gather_table_stats('HR','TAB',cascade=>true,method_opt=>'FOR COLUMNS B SIZE 1');
但这却得再次收集表的统计信息,十分不合理,11g有如下方法可以直接删除直方图信息
dbms_stats.delete_column_stats(ownname => user,
tabname => 'T',
colname => 'VAL',
col_stat_type => 'HISTOGRAM')

时间: 2025-01-30 10:47:19

如何看懂oracle 直方图的相关文章

彻底搞懂Oracle字符集

以下是对Oracle中的字符集进行了详细的分析介绍,需要的朋友可以参考下   基本概念字符集(Character set):是一个系统支持的所有抽象字符的集合.字符是各种文字和符号的总称,包括各国家文字.标点符号.图形符号.数字等.常见的字符集有ASCII,ZHS16GB231280,ZHS16GBK等. 字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其它的一个集合(如电脑编码)进行配对.即在符号集合与数字系统之间建

看懂SqlServer查询计划

原文:看懂SqlServer查询计划 对于SQL Server的优化来说,优化查询可能是很常见的事情.由于数据库的优化,本身也是一个涉及面比较的广的话题, 因此本文只谈优化查询时如何看懂SQL Server查询计划.毕竟我对SQL Server的认识有限,如有错误,也恳请您在发现后及时批评指正. 首先,打开[SQL Server Management Studio],输入一个查询语句看看SQL Server是如何显示查询计划的吧. 说明:本文所演示的数据库,是我为一个演示程序专用准备的数据库,

教你如何看懂SQL Server查询计划_MsSql

对于SQL Server的优化来说,优化查询可能是很常见的事情.由于数据库的优化,本身也是一个涉及面比较的广的话题,因此本文只谈优化查询时如何看懂SQL Server查询计划.毕竟我对SQL Server的认识有限,如有错误,也恳请您在发现后及时批评指正. 首先,打开[SQL Server Management Studio],输入一个查询语句看看SQL Server是如何显示查询计划的吧. 说明:本文所演示的数据库,是我为一个演示程序专用准备的数据库,可以在此网页中下载. select v.O

[Oracle] 彻底搞懂Oracle字符集_oracle

基本概念字符集(Character set):是一个系统支持的所有抽象字符的集合.字符是各种文字和符号的总称,包括各国家文字.标点符号.图形符号.数字等.常见的字符集有ASCII,ZHS16GB231280,ZHS16GBK等.字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其它的一个集合(如电脑编码)进行配对.即在符号集合与数字系统之间建立对应关系.与字符集相对应,常见的字符编码有:ASCii,ZHS16GBK,ZH

Oracle直方图

Oracle直方图 直方图是一种按数据出现的频率来进行分类存储的方法.在oracle中直方图是用来描述表中列数据的分布情况.每一个sql在被执行前都要经过优化这一步骤那么在优化器给出一个最优执行计划之优化器应该要知道sql语句中所引用的底层对象的详细信息. 直方图描述的对象包括列中不同值的数量和它们出现的频率.现在存储每一个不同值和它出现的频率是不可行的,特别是对于大表来说列中有上万个不同值,oracle使用直方图来存储关于列中数据分布的有用信息而且oracle的CBO使用直方图信息来计算出一个

oracle 直方图

转: 一.    何谓直方图: 直方图是一种统计学上的工具,并非Oracle专有.通常用于对被管理对象的某个方面的质量情况进行管理,通常情况下它会表现为一种几何图形表,这个图形表是根据从实际环境中所收集来的被管理对象某个方面的质量分布情况的数据所绘制成的,通常会画成以数量为底边,以频度为高度的一系列连接起来的矩形图,因此直方图在统计学上也称为质量分布图.比如下图所示,是一个以关学生化学考试成绩分数分布情况绘制的直方图:       二.       Oracle中直方图的作用: 既然直方图是一种

教你如何看懂SQL Server查询计划

对于SQL Server的优化来说,优化查询可能是很常见的事情.由于数据库的优化,本身也是一个涉及面比较的广的话题,因此本文只谈优化查询时如何看懂SQL Server查询计划.毕竟我对SQL Server的认识有限,如有错误,也恳请您在发现后及时批评指正. 首先,打开[SQL Server Management Studio],输入一个查询语句看看SQL Server是如何显示查询计划的吧. 说明:本文所演示的数据库,是我为一个演示程序专用准备的数据库,可以在此网页中下载. select v.O

先看懂列表,再正确使用列表

  引言 随着公司朝互联网转型的脚步,目前我们已经有几十个移动APP上线,但是各个应用之间的设计策略和规范的差异性导致我们自身的设计品牌难以凸显,略显杂乱;而交互原则的差异性则导致每个应用之间的交互方式差异颇大,明明是同一个系列同一个类型的应用,却用了两种截然不同的交互框架,给用户的学习和使用上带了了很多不便. 在这种情况下,我们用户体验部通过成立这个移动专项研究小组来进行分步骤.长期的移动应用设计模式研究,希望能够通过我们的努力,不断改进我们的移动应用设计模式,最终将我们金蝶品牌的移动应用在易

如何让搜索引擎看懂你的网站结构层次

听到这个标题有些阅读者认为这很俗气,所说的越是俗气东西,别人才关注,呵呵!从标题看出来,这也明确的表达出来意思,就是让搜索引擎看懂你的网站是干什么,网站层次结构合不合理,如果说搜索引擎看不懂,更别提客户能看懂你的意思.所以说这个也网站结构占了很大比例,网站结构层次很清晰,你的网站就会容易受到百度蜘蛛的欢迎,会很快收录你的网站内容. 一.网站结构要像"树" 为什么说要像"树结构",从图   从这个图中我可以看出来,客户或者搜索引擎很快就能找到它想要的东西,很清晰的表达