ǰλã >> ݿ >> ORACLE Histograms (直方
  ϸ

ORACLE Histograms (直方

ȶȣ5124   ʱ䣺2013-02-26 00:00:00.0
ORACLE Histograms (直方?

?.何谓直方图:

直方图是?种统计?上的工具,并非Oracle专有。?常用于对?管理对象的某?面的质量情况进?管理,?常情况下它会表现为?种几何图形表,这?形表??实际???收集来的??理?象某?面的质量分布情况的数?绘制成的,?常会画成以数量为底边,以?度为高度的一系列连接起来的矩形图,因此直方图在统计?上也称为质量分布图?比如下图所示,??关?生化学?试成绩分数分布情况绘制的直方图?/p>

 

?Oracle?方图的作?

既然直方图是?种???理?象某?方面质量进?管理的描述工具,那么在Oracle?然它也是对Oracle???象质量的描述工具,这??象就是Oracle?重?的东西???数????/p>

在Oracle?方图?种?数据分布质量情况进?描述的工具?它会按照某?列不同?出现数量?少,以及出现的?率高低来绘制数据的分布情况,以便能?指?优化器根??分布做出正确的?择。在某些情况下,表的列中的数值分布将会影响优化器使用索引还是执?全表?的决策?当 where 子句的?具有不成比例数量的数?时,将出现这?情况,使得全表扫描比索引访问的成?低?这种情况下如果where 子句的过滤谓词列之上上有??理的正确的直方图,将会?优化器做出??选择发挥巨大的作?使得SQL?执?成本?低从而提升?能?/p>

?Oracle?用直方图的场合:

在分析表或索引时,直方图用于记录数据的分布??过获得该信?基于成本的优   化器就可以决定使用将返回少量行的索引,?避免使用基于限制条件返回?多?的索引?直方图的使用不受索引的限制,可以在表的任何列上构建直方图??/p>

构?直方图?主?的原因就?助优化器在表??重偏斜时做出更好的?划:例?,?果一到两??构成了表中的大部分数据(数据偏斜),相关的索引就可能无法帮助减少满足查询所?的I/O数量。创建直方图?让基于成?优化器知道何时使用索引才?合?,或何时应该根据WHERE子句?值返回表?0%的记录?/p>

通常情况下在以下场合??用直方图?/p>

 ?)?当Where子句引用了列值分布存在明显偏?列时:当这?偏差相当明显时,以至?WHERE 子句?值将会使优化器?择不同的执行?划?这时应该使用直方图来帮助优化器来修正执行路径?(注意:?果查?引用该列,则创建直方图没有意义?这种错?常?,??DBA 会在偏差列上创建柱状图,即使没有任何查?引用该列。)

?)?当列??致不正确的判?:这种情况?常会发生在多表连接时,例?,假设我???项的表联接,其结果集? 10 行?Oracle 将会以一种使??接的结果集(集合基数)尽?小的方式将表联接起来。?过在中间结果集?带更少的负载,查询将会运行得更快。为了使?结果?小化,优化器尝试?SQL 执?的分析阶段评估每?果集的集合基数?在偏差的列上拥有直方图将会极大地帮助优化器作出正确的决策??优化器??结果集的大小作出不??判断,它?会?择?种未达到?优化的表联接方法。因此向该列添加直方图经常会向优化器提供使用?佳联接方法所?的信???/p>

?直方图有两?类别,等频直方图与等高直方图?/p>

默?的,如果???斜列上的唯?值超过了254?那么ORACLE会?此列建立等高直方图,否则建立等?直方图??/p>

通过如下方式,建立表TAB,更新字段B,?列B产生倾斜。并在B列上创建索引?/p>

SQL> spool d:\hist.txt

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

 

表已创建?/p>

 

SQL>

SQL> begin

  2         for i in 1..10000 loop

  3           insert into tab values (i, i);

  4         end loop;

  5         commit;

  6       end;

  7       /

 

PL/SQL 过程已成功完成??/p>

 

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

 

已更?990行??/p>

SQL> commit;

 

提交完成?/p>

 

SQL> create index ix_tab_b on tab(b);

 

索引已创建??/p>

 

 

然后分析?强制使列B不产生直方图?/p>

BEGIN

  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME    => 'SCOTT',

                                TABNAME    => 'TAB',

                                CASCADE    => TRUE,

                                METHOD_OPT => 'FOR  COLUMNS B SIZE 1 ');

END;

查看视图USER_TAB_HISTOGRAMS,列B上只有最大?,?小?两条?录分??应?点号(endpoint_number??,这种显示?明列B没有直方图信???/p>

SQL>SELECT table_name,column_name,endpoint_number,endpoint_value FROM USER_TAB_HISTOGRAMS WHERE TABLE_NAME='TAB' ?/p>

 

TABLE_NAME                     COLUMN_NAME                              ENDPOINT_NUMBER ENDPOINT_VALUE

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

TAB                            B                                                      0              1

TAB                            B                                                      1          10000

 

在没有直方图的情况下,在B列上进?等?查询的时?,都是索引范围??/p>

 

SQL> select * from tab where b=1;

 

 

执?计划

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

Plan hash value: 439197569

 

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

| 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          | IX_TAB_B |  1000 |       |     2   (0)| 00:00:01 |

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

 

 

SQL> select * from tab where b=5;

 

已?择9991行??/p>

 

 

执?计划

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

Plan hash value: 439197569

 

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

| 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          | IX_TAB_B |  1000 |       |     2   (0)| 00:00:01 |

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

收集直方图信??看看是?么效果?由于列B?值的?没有超过254因?产生的是等?直方图??/p>

BEGIN

  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME    => 'SCOTT',

                                TABNAME    => 'TAB',

                                CASCADE    => TRUE,

                                METHOD_OPT => 'FOR ALL COLUMNS  SIZE AUTO ');

END;

 

在B=1时?采用索引扫描,而B=5时?,已经采用全表?了,说明直方图起了作用??/p>

SQL> select * from tab where b=1;

 

 

执?计划

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

Plan hash value: 439197569

 

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

| 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          | IX_TAB_B |     1 |       |     1   (0)| 00:00:01 |

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

 

SQL> select * from tab where b=5;

 

已?择9991行??/p>

 

 

执?计划

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

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 |

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

 

 

 

查看此时的直方图信息?/p>

SQL>SELECT TABLE_NAME, COLUMN_NAME, ENDPOINT_NUMBER, ENDPOINT_VALUE FROM USER_TAB_HISTOGRAMS

WHERE TABLE_NAME = 'TAB'?/p>

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

 

其中EDNPOINT_NUMBER?计??EDNPOINT_VALUE?的??可以看出这种等频直方图统?的列的信?非常精确的?它为每??值分配了??。从执?计划的ROWS部分也可以看出ORACLE计算出来的cardinality?991,和实际的情况完全吻合??/p>

如果想知道每??值?应的数量??少,?要做?下简单的减法运算?/p>

假?想知道列值等?的个数,那么?通过?/p>

9995-4=9991得到。这就是ENDPOINT_NUMBER??值的??/p>

在看看等高直方图的情况??/p>

BEGIN

  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME    => 'SCOTT',

                                TABNAME    => 'TAB',

                                CASCADE    => TRUE,

                                METHOD_OPT => 'FOR  COLUMNS B SIZE 8 ');

END;

 

由于列B?0??值,通过上面的size 8?强制ORACLE使用等高直方图??/p>

查看直方图信?

SQL>SELECT TABLE_NAME, COLUMN_NAME, ENDPOINT_NUMBER, ENDPOINT_VALUE FROM USER_TAB_HISTOGRAMS

WHERE TABLE_NAME = 'TAB'?/p>

 

TABLE_NAME                     COLUMN_NAME                              ENDPOINT_NUMBER ENDPOINT_VALUE

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

TAB                            B                                                      0              1

TAB                            B                                                      7              5

TAB                            B                                                      8          10000

 

从查询结果惊奇的发现?三个? 7 8,原?RACLE会自动省去EDNPOINT_VALUE值相同且ENDPOINT_NUMBER相邻的桶的???/p>

省去了桶(EDNPOINT_NUMBER)为1 2 3 4 5 6 ,EDNPOINT_VALUE?的六条内容??/p>

 

 

说明:在等高直方图中,EDNPOINT_NUMBER代表桶号,这一点与等?直方图不同??/p>

 

再看等高直方图下的执行?划:

 

SQL> select * from tab where b=5;

已?择9991行??/p>

 

执?计划

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

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 |

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

 

 

有没有发现什么?

 

执?计划的ROWS部分,ORACLE计算出来的cardinality不是特别精确的??991才是精确值??等频直方图?精确?991,因此可以?等?直方图比等高直方图稳定,精确?/p>

?现实很?时?,列的?值是超过254的?只能使用等高直方图了??/p>