当不重复值的数量大于允许的桶的最大数量(使用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版本开始,高频率直方图和混合直方图替代了高度均衡直方图。




