暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

oracle 直方图 - 高度均衡直方图

原创 不吃草的牛_Nick 2023-09-18
270

当不重复值的数量大于允许的桶的最大数量(使用dbms_stats包时,会有一个硬性限制,甚至有可能会指定一个更低的值)时,你就无法使用频率直方图,因为每个桶只支持一个单独的值。此时就该高度均衡直方图施展身手了。

 

要创建一个高度均衡直方图,考虑一下接下来的过程。首先,创建出一个频率直方图。然后,如图8-3所示,频率直方图的值被堆积成一“堆”。最后,这个“堆”再被分成几个具有相同高度的桶。例如,在图8-3中,“堆”被分到了五个桶中。



下面的查询是一个如何为val2列生成一个高度均衡直方图的例子。图8-4展示了这个查询返回数据的一个图示。注意每个桶的端点值正是拆分数据出现的点。此外,桶0被添加进来用以存储最小值:

SELECT count(*), max(val2) AS endpoint_value, endpoint_number

FROM (

  SELECT val2, ntile(5) OVER (ORDER BY val2) AS endpoint_number

  FROM t

)

GROUP BY endpoint_number

ORDER BY endpoint_number;

 

COUNT(*)  ENDPOINT_VALUE   ENDPOINT_NUMBER

200         104                1

200         105                2

200         105                3

200         106                4

200         106                5



针对图8-4中的案例,接下来的查询展示了存储在数据字典中的高度均衡直方图。有趣的是,并没有存储所有的桶。之所以没有存储所有的桶是因为,几个拥有相同端点值的相邻桶没有多大用处。实际上,从显示出来的数据可以推断出,桶2的端点值是105,而桶4的端点值为106。查询结果有点浓缩的意思。在直方图中出现多次的值被称为常见值,并且会被查询优化器特殊处理:

SELECT endpoint_value, endpoint_number

FROM user_tab_histograms

WHERE table_name = 'T'

AND column_name = 'VAL2'

ORDER BY endpoint_number;

 

ENDPOINT_VALUE   ENDPOINT_NUMBER

  101                0

  104                1

  105                3

  106                5

 

下面是高度均衡直方图的主要特性。

Ø  桶的数量少于不重复值的数量。对于每一个桶,除非它们进行了压缩,否则都在像user_tab_histograms这样的视图中有一条带有端点号的记录与之对应。此外,端点号0表明是最小值。

Ø  endpoint_value列给出关于值本身的数字表示形式。

Ø  endpoint_number列给出桶的编号。

Ø  直方图不存储值的频率。

 

下面的例子展示了当存在合适的高度均衡直方图时查询优化器所作的估算。注意与频率直方图相比相对较低的精确度:

DELETE plan_table;

EXPLAIN PLAN SET STATEMENT_ID '101' FOR SELECT * FROM t WHERE val2 = 101;

EXPLAIN PLAN SET STATEMENT_ID '102' FOR SELECT * FROM t WHERE val2 = 102;

EXPLAIN PLAN SET STATEMENT_ID '103' FOR SELECT * FROM t WHERE val2 = 103;

EXPLAIN PLAN SET STATEMENT_ID '104' FOR SELECT * FROM t WHERE val2 = 104;

EXPLAIN PLAN SET STATEMENT_ID '105' FOR SELECT * FROM t WHERE val2 = 105;

EXPLAIN PLAN SET STATEMENT_ID '106' FOR SELECT * FROM t WHERE val2 = 106;

 

COLUMN statement_id FORMAT A12

 

SELECT statement_id, cardinality

FROM plan_table

WHERE id = 0

ORDER BY statement_id;

 

STATEMENT_ID   CARDINALITY

101              50

102              50

103              50

104              50

105              400

106              300

 

注意 你可能认为关于值105和106的基数估算完全一样(400,因为这两个高频率值都占了桶数量的2/5)。但是对于值106,却不是这样。这是因为,查询优化器在出现一个常见值同时也是直方图的最大值时,调整了估算的结果。

 

同样对于这种类型的直方图,我们来看一下当使用了直方图中没有体现的值时会发生什么。此时需要考虑两种完全不同的情况。

第一,如果值在最小值和最大值之间,查询优化器会使用与其他非常见值一样的频率。

第二,如果值在直方图涵盖的值范围之外,则频率依赖于其到最小值或最大值的距离。

 

下面的例子证明了这一点:

DELETE plan_table;

EXPLAIN PLAN SET STATEMENT_ID '096' FOR SELECT * FROM t WHERE val2 = 96;

EXPLAIN PLAN SET STATEMENT_ID '098' FOR SELECT * FROM t WHERE val2 = 98;

EXPLAIN PLAN SET STATEMENT_ID '100' FOR SELECT * FROM t WHERE val2 = 100;

EXPLAIN PLAN SET STATEMENT_ID '103.5' FOR SELECT * FROM t WHERE val2 = 103.5;

EXPLAIN PLAN SET STATEMENT_ID '107' FOR SELECT * FROM t WHERE val2 = 107;

EXPLAIN PLAN SET STATEMENT_ID '109' FOR SELECT * FROM t WHERE val2 = 109;

EXPLAIN PLAN SET STATEMENT_ID '111' FOR SELECT * FROM t WHERE val2 = 111;

 

COLUMN statement_id FORMAT A12

 

SELECT statement_id, cardinality

FROM plan_table

WHERE id = 0

ORDER BY statement_id;

 

STATEMENT_ID   CARDINALITY

096                1

098                20

100                40

103.5              50

107                40

109                20

111                1

 

就这两种类型直方图的这些关键特性而论,很明显频率直方图要比高度均衡直方图更加精确。高度均衡直方图的主要问题不仅仅是精确度更低,而且有时候可能会意外导致一个值被当做常见值。例如,在图8-4所示的直方图中,桶4和桶5之间的拆分点非常接近于值从105变为106的点上。

 

因此,即使是数据分布非常微小的变化也可能导致一个不同的直方图以及不同的估算结果。在下面的例子中,只有20条记录被更新(约占总记录数的2%),就展示了这样的一种情况:

UPDATE t SET val2 = 105 WHERE val2 = 106 AND rownum <= 20;

 

BEGIN

  dbms_stats.gather_table_stats(

    ownname          => user,

    tabname          => 'T',

    estimate_percent => 100,

    method_opt       => 'for columns val2 size 5',

    cascade          => TRUE

  );

END;

/

 

SELECT endpoint_value, endpoint_number

FROM user_tab_histograms

WHERE table_name = 'T'

AND column_name = 'VAL2'

ORDER BY endpoint_number;

 

ENDPOINT_VALUE   ENDPOINT_NUMBER

  101                0

  104                1

  105                4

  106                5

DELETE plan_table;

EXPLAIN PLAN SET STATEMENT_ID '101' FOR SELECT * FROM t WHERE val2 = 101;

EXPLAIN PLAN SET STATEMENT_ID '102' FOR SELECT * FROM t WHERE val2 = 102;

EXPLAIN PLAN SET STATEMENT_ID '103' FOR SELECT * FROM t WHERE val2 = 103;

EXPLAIN PLAN SET STATEMENT_ID '104' FOR SELECT * FROM t WHERE val2 = 104;

EXPLAIN PLAN SET STATEMENT_ID '105' FOR SELECT * FROM t WHERE val2 = 105;

EXPLAIN PLAN SET STATEMENT_ID '106' FOR SELECT * FROM t WHERE val2 = 106;

 

COLUMN statement_id FORMAT A12

 

SELECT statement_id, cardinality

FROM plan_table

WHERE id = 0

ORDER BY statement_id;

 

STATEMENT_ID   CARDINALITY

101              80

102              80

103              80

104              80

105              600

106              80

 

因此,在实践中,高度均衡直方图可能不仅会令人误解,同时也会导致查询优化器估算的不稳定性。为了不再使用它们,自12.1版本开始,高频率直方图和混合直方图替代了高度均衡直方图。

 

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论