`

Oracle 直方图

 
阅读更多
文章整理来源于:
剑破冰山之Oracle开发
http://www.dbform.com/html/2010/1200.html

--下面来先关组下ORACLE的预测行对执行计划的影响。
DROP TABLE T PURGE;
CREATE TABLE T(ID,COL1,COL2)
AS
SELECT ROWNUM,CASE WHEN ROWNUM >100 THEN 200 ELSE ROWNUM END,ROWNUM
FROM DUAL
CONNECT BY LEVEL <=10000;

CREATE INDEX T_COL1 ON T(COL1);
admin@ORCL> SELECT COUNT(*) FROM T WHERE COL1=200;

  COUNT(*)
----------
      9900

admin@ORCL> SELECT COUNT(*) FROM T WHERE COL1<>200;

  COUNT(*)
----------
       100

--收集表统计信息,但不收集直方图(SIZE 1即不收集)
admin@ORCL> BEGIN
  2  DBMS_STATS.GATHER_TABLE_STATS(
  3  'ADMIN',
  4  'T',
  5  CASCADE=>TRUE,
  6  ESTIMATE_PERCENT=>100,
  7  METHOD_OPT=>'FOR ALL COLUMNS SIZE 1',
  8  NO_INVALIDATE=>FALSE);
  9  END;
 10  /

--查看执行计划,返回的行数实际上应为为9900,而Oracle预估的返回行数为99,导致Oracle认为走索引效率比较高。这是个比较错误的执行计划。


admin@ORCL> SELECT * FROM T WHERE COL1 = 200;
已选择9900行。
执行计划
----------------------------------------------------------
Plan hash value: 1192298089
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |    99 |   990 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |    99 |   990 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_COL1 |    99 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("COL1"=200)
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1363  consistent gets
          0  physical reads
          0  redo size
     212731  bytes sent via SQL*Net to client
       7634  bytes received via SQL*Net from client
        661  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       9900  rows processed

--了解下Oracle在没有收集直方图的情况下,如何计算出COL1 = 200的返回行数
admin@ORCL> SELECT COUNT(DISTINCT COL1) FROM T;

COUNT(DISTINCTCOL1)
-------------------
                101
admin@ORCL> SELECT COUNT(*) FROM T;

  COUNT(*)
----------
     10000
--Oracle 会认为COL1每个值都是均匀分布的
admin@ORCL> select round(10000/101) from dual;

ROUND(10000/101)
----------------
              99

--全面收集行的直方图

admin@ORCL> BEGIN
  2  DBMS_STATS.GATHER_TABLE_STATS(
  3  'ADMIN',
  4  'T',
  5  CASCADE=>TRUE,
  6  ESTIMATE_PERCENT=>100,
  7  METHOD_OPT=>'FOR ALL COLUMNS SIZE 254',
  8  NO_INVALIDATE=>FALSE);
  9  END;
 10  /
 
--Oracle选择了正确的执行计划:全表扫描,逻辑读也从1363->685
admin@ORCL> SELECT * FROM T WHERE COL1 = 200;
已选择9900行。
执行计划
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  9900 | 99000 |     8   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |  9900 | 99000 |     8   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("COL1"=200)
统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        685  consistent gets
          0  physical reads
          0  redo size
     212731  bytes sent via SQL*Net to client
       7634  bytes received via SQL*Net from client
        661  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       9900  rows processed


--我们来仔细研究下Oracle是如何存储列的直方图信息
--直方图的类型有三种

None: 没有直方图
Frequency: 频率直方图
HEIGHT BALANCED: 等高直方图

--当该列的distinct值数量<=bucket数量时,直方图的类型为FREQUENCY,否者为HEIGHT BALANCE
admin@ORCL> SELECT COLUMN_NAME,NUM_DISTINCT,NUM_BUCKETS,HISTOGRAM FROM DBA_TAB_COL_STATISTICS WHERE TABLE_NAME = 'T' AND OWNER = 'ADMIN';

COLUMN_NAME          NUM_DISTINCT NUM_BUCKETS HISTOGRAM
-------------------- ------------ ----------- ---------------
ID                          10000         254 HEIGHT BALANCED
COL1                          101         101 FREQUENCY
COL2                        10000         254 HEIGHT BALANCED

--col1的直方图类型为Frequency,
--在DBA_TAB_HISTOGRAMS视图中,字段endpoint_value就对应字段COL1的值,
--而endpoint_number对应字段COL1值的记录条数。注意:这里的记录条数是累加的。

admin@ORCL> SELECT COLUMN_NAME, ENDPOINT_NUMBER, ENDPOINT_VALUE
  2    FROM DBA_TAB_HISTOGRAMS
  3   WHERE OWNER = 'ADMIN'
  4     AND TABLE_NAME = 'T'
  5     AND COLUMN_NAME = 'COL1';


COLUMN_NAME          ENDPOINT_NUMBER ENDPOINT_VALUE
-------------------- --------------- --------------
COL1                               1              1
COL1                               2              2
COL1                               3              3
COL1                               4              4
COL1                               5              5
COL1                               6              6
COL1                               7              7
COL1                               8              8
COL1                               9              9
COL1                              10             10
....                              ..             ..
COL1                              98             98
COL1                              99             99
COL1                             100            100
COL1                           10000            200

--Frequency直方图的统计方式应该就等同于下面的sql
admin@ORCL> SELECT COL1 AS ENDPONT_VALUE,COUNT(*) AS CNT,SUM(COUNT(*)) OVER(ORDER BY COL1) AS ENDPOINT_NUM FROM T GROUP BY COL1 ORDER BY COL1

ENDPONT_VALUE        CNT ENDPOINT_NUM
------------- ---------- ------------
            1          1            1
            2          1            2
            3          1            3
            4          1            4
            5          1            5
            6          1            6
            7          1            7
            8          1            8
            9          1            9
           10          1           10
           ..          .           ..
           98          1           98
           99          1           99
          100          1          100
          200       9900        10000

已选择101行。
--我们看看直方图类型为HEIGHT BALANCE类型时,是如何存储的
--为了方便演示,这里SIZE 250表示250个bucket来存放数据
admin@ORCL> BEGIN
  2   DBMS_STATS.GATHER_TABLE_STATS(
  3   'ADMIN',
  4   'T',
  5   CASCADE=>TRUE,
  6   ESTIMATE_PERCENT=>100,
  7   METHOD_OPT=>'FOR ALL COLUMNS SIZE 250',
  8   NO_INVALIDATE=>FALSE);
  9  END;
 10  /

PL/SQL 过程已成功完成。

--查看直方图信息
admin@ORCL> SELECT COLUMN_NAME,NUM_DISTINCT,NUM_BUCKETS,HISTOGRAM FROM DBA_TAB_COL_STATISTICS WHERE TABLE_NAME = 'T' AND OWNER = 'ADMIN';

COLUMN_NAME          NUM_DISTINCT NUM_BUCKETS HISTOGRAM
-------------------- ------------ ----------- ---------------
ID                          10000         250 HEIGHT BALANCED
COL1                          101         101 FREQUENCY
COL2                        10000         250 HEIGHT BALANCED


admin@ORCL> SELECT COLUMN_NAME, ENDPOINT_NUMBER, END
  2    FROM DBA_TAB_HISTOGRAMS
  3   WHERE OWNER = 'ADMIN'
  4     AND TABLE_NAME = 'T'
  5     AND COLUMN_NAME = 'ID';

COLUMN_NAME          ENDPOINT_NUMBER ENDPOINT_VALUE
-------------------- --------------- --------------
ID                                 0              1
ID                                 1             40
ID                                 2             80
ID                                 3            120
ID                                 4            160
ID                                 5            200
ID                                 6            240
ID                                 7            280
ID                                 8            320
ID                                 9            360
ID                                10            400
..                                ..            ...
ID                               248           9920
ID                               249           9960
ID                               250          10000

--这里的ENDPOINT_NUMBER不再表示记录的条数,它标示BUCKET(桶)的编号,ENDPOINT_VALUE的算法如下:
--记录条数为10000条,共分配到250个桶中,那么每个桶的数据量为40条记录
第一个ENDPOINT_VALUE的值相当于如下SQL的返回值。
admin@ORCL> select max(ID) from (select ID from t order by ID) where rownum<=40;

   MAX(ID)
----------
        40

第二个ENDPOINT_VALUE的值相当于如下SQL的返回值。
admin@ORCL> select max(ID) from (select ID from t order by ID) where rownum<=40*2;

   MAX(ID)
----------
        80

第三个ENDPOINT_VALUE的值相当于如下SQL的返回值。
admin@ORCL> select max(ID) from (select ID from t order by ID) where rownum<=40*3;

   MAX(ID)
----------
       120
/*
依次类推。正是这样的信息告诉了Oracle数据的分布情况,试想一下,如果连续3个bucket的ENDPOINT_VALUE值都10,
那么也就是说至少有2个bucket中的记录N2字段都是10,也就是说ID=10的记录至少有80条,越多的bucket有越多相同的ENDPOINT_VALUE值,
就表明数据分布越不均匀。
有一点需要额外注意的是:如果某几个bucket的ENDPOINT_VALUE值相同,那么在视图中只会记录最后一个bucket的信息。
*/

--何时应该收集直方图

首先我们要明确直方图信息是有存在的必要的,但是只应该存在在那些应该要存在的列上。或者说我们希望对不不同的字段值走不同的执行计划时
才考虑收集直方图。

--反过来说,什么情况下我们不需要直方图呢?或者说直方图的存在是没有意义的呢?
1. 当此列不用于查询时,也就是这个字段永远不会出现在where条件中(注意:即使是用于表连接那也算是出现在where条件中)。
2. 当此列无论给予什么比较值,我们都希望永远是一种执行计划时。

 

分享到:
评论

相关推荐

    Oracle 直方图计算

    Oracle 直方图计算公式,对于Oracle cbo优化器的探究又进入一步

    Oracle 直方图解析.pdf

    ### Oracle直方图解析深度解读 #### 一、直方图概述 直方图作为一种统计学工具,在Oracle数据库中扮演着关键角色。本质上,直方图是对数据分布情况的一种图形化表示,它通过一系列相连的矩形来展示数据在各个区间...

    Oracle直方图.pdf

    Oracle直方图是数据库优化的重要工具,特别是在Oracle关系型数据库中,它对于Cost-Based Optimizer (CBO)的成本估算起到关键作用。直方图能够帮助CBO更准确地理解数据表列的数据分布,从而制定出更高效的查询执行...

    结合实例深入讲解oracle中的直方图histogram

    ### 结合实例深入讲解Oracle中的直方图Histogram #### 一、直方图的基本概念 直方图是一种统计图表,在多种领域中都有广泛的应用,它并非Oracle数据库所独有的功能。直方图通常用来描绘一组数据的分布情况,通过一...

    oracle优化直方图

    在探讨Oracle优化直方图之前,需要对优化器的概念有所了解。优化器在数据库中扮演着非常重要的角色,它负责生成执行计划,决定如何高效地从数据库中检索数据。优化器有两种类型:基于规则的优化器(RBO)和基于成本...

    【Maclean Liu技术分享】拨开Oracle CBO优化器迷雾,探究Histogram直方图之秘_0321.pdf

    ### Oracle CBO优化器与直方图(Histogram)解析 #### 概述 在数据库管理领域,Oracle CBO(Cost-Based Optimizer)成本基于优化器是Oracle数据库管理系统中用于确定查询执行计划的一种重要机制。通过分析SQL语句,...

    C#绘制直方图,饼图,曲线图

    数据可以从数据库查询得到,通过ADO.NET连接Oracle数据库,执行SQL语句获取数据,然后对数据进行分组和计算频率,最后根据结果绘制直方图。 饼图则用于显示一个数据系列中各项的大小与各项总和的比例关系。在C#中,...

    乔晓阳 - 一个直方图问题引发的思考

    标题中提及的“一个直方图问题引发的思考”指向的是在Oracle数据库环境下,对直方图和SQL执行计划的深入分析和优化过程。直方图是Oracle数据库中用于记录列内值分布的统计工具,它在优化器选择执行计划时起到关键...

    oracle histograms

    在使用直方图时,Oracle优化器会根据直方图信息来调整其基数估计方法,以便更准确地预测查询结果的行数。这些调整包括对特定查询谓词(如等值、范围和不等于)的处理。 例如,对于等值谓词,优化器将基于直方图的桶...

    SQL执行计划与直方图关系研究.pdf

    文章提到,收集准确的统计信息,特别是直方图的收集,对于Oracle能否选择最优的执行计划至关重要。通过实验验证,直方图对SQL执行计划的影响非常明显,可以清楚地指导数据库管理员在哪些情况下需要收集直方图。 ...

    Oracle中直方图对执行计划的影响详解

    总结来说,直方图在Oracle数据库中对执行计划有着显著影响。它可以纠正CBO对数据分布的错误假设,避免因数据倾斜而导致的不理想执行计划,如全表扫描,而选择更适合的索引操作。在处理倾斜数据或需要精确统计信息的...

    ORACLE 数据库的统计数据及优化

    3. **直方图统计**:支持创建直方图来更好地描述列值的分布情况,这对于处理数据倾斜的情况非常有用。 #### 五、`dbms_stats`的主要参数详解 - **options参数**:控制Oracle统计的刷新方式。提供了四种预设方法: ...

    Oracle数据库优化详解

    - 介绍了直方图(Histogram)的概念、收集方法及其对选择性的影响。 - 讨论了表连接的不同方式,如排序-合并连接(SMJ)、嵌套循环(NL)、哈希连接(HJ)等,并比较了它们的特点。 - 分析了笛卡儿乘积产生的原因...

    影响Oracle数据库索引的几个因素浅析.pdf

    影响Oracle数据库索引的几个因素包括选择性、集群因子、二元高度和直方图等。本文通过对索引的概念和作用的剖析,以及对影响索引的几个因素的分析,旨在帮助数据库管理员更好地理解和应用索引技术。 六、参考文献 ...

    OracleSql规则与优化

    综上所述,Oracle SQL的规则与优化涉及了从SQL语句的分类、执行流程、解析策略到绑定变量的使用、直方图的构建等多个方面。理解并熟练应用这些知识点,不仅可以提升SQL执行效率,还能为整个系统的性能优化打下坚实的...

    Oracle性能优化培训

    - 直方图可以帮助Oracle更准确地估计查询的行数。 - 聚簇因子表示索引条目与实际数据之间的距离,其值越低表明索引的效率越高。 - 动态采样技术可以使Oracle更精确地估算查询成本,从而选择更优的执行计划。 - *...

    Oracle常用dump命令介绍

    - **2**:包含哈希表直方图 (Hashtab Histogram)。 - **3**:包含对象句柄 (Object Handle)。 - **4**:包含对象结构 (Heap0)。 通过调整 `n` 的值,可以获取Library Cache的不同层面的信息。 ##### 3\. Row ...

Global site tag (gtag.js) - Google Analytics