注册
达梦数据库直方图统计信息实验
培训园地/ 文章详情 /

达梦数据库直方图统计信息实验

阿白 2023/02/15 1452 1 0

实验目的

在收集统计信息时,若要生成直方图统计信息,则我们知道达梦数据库的统计信息分为 两种(频率直方图和等高直方图)。而这两种直方图的默认界限是 NDV(Number of Distinct Values)值是否大于 10000。 
如果 NDV 值等于 9999 呢?明明也适合等高直方图,却就是频率直方图。这样会影响 最终执行计划的生成。对于初期业务设计会起到很不好的影响。 
我希望在如上所述的场景里可以收集等高直方图,特设计了这个实验。 

环境准备

二级标题

建表语句:
create table h(x number);
数据准备:
declare i number;
begin
for i in 1…3296 loop
insert into h values (1);
end loop;

for i in 1…100 loop
insert into h values (3);
end loop;

for i in 1…798 loop
insert into h values (5);
end loop;

for i in 1…3970 loop
insert into h values (7);
end loop;

for i in 1…16293 loop
insert into h values (10);
end loop;

for i in 1…3399 loop
insert into h values (16);
end loop;

for i in 1…3651 loop
insert into h values (27);
end loop;

for i in 1…3892 loop
insert into h values (32);
end loop;

for i in 1…3521 loop
insert into h values (39);
end loop;

for i in 1…1080 loop
insert into h values (49);
end loop;

commit;
end;
/
环境介绍:
H 表中插入了 40000 条语句 10 个不同值,查询结果如下:
SQL> select x as x, count() as cardinality,
sum(count(
)) over (order by x range unbounded preceding) as cum_cardinality
from h
group by x;
行号 X CARDINALITY CUM_CARDINALITY


1 1 3296 3296
2 3 100 3396
3 5 798 4194
4 7 3970 8164
5 10 16293 24457
6 16 3399 27856
7 27 3651 31507
8 32 3892 35399
9 39 3521 38920
10 49 1080 40000

10 rows got

已用时间: 54.409(毫秒). 执行号:500.

概念理解

频率直方图:ndv 和直方图中桶数一样的直方图。
等高直方图:ndv 和直方图中桶数不等的直方图。

猜想

只要设置 ndv 和直方图中桶数不等即可达到实验目的。

开始实验

默认情况

初步收集表统计信息如下:
SQL> stat 100 on h(x); --收集默认百分比为 100%,其他情况皆为默认
操作已执行
已用时间: 39.538(毫秒). 执行号:501.
查询统计信息如下:
SQL> SELECT id,n_distinct,n_buckets FROM SYSSTATS where id=6518;

行号 ID N_DISTINCT N_BUCKETS


1 6518 0 0
2 6518 10 10

已用时间: 1.165(毫秒). 执行号:502.
此时系统默认收集直方图可以看出是频率直方图。
接下来我们继续实验非默认情况。

设置直方图的桶数

100 等分

SQL> stat 100 size 100 on h(x); --将 10 个不同值放入到 100 个桶里 操作已执行
已用时间: 32.189(毫秒).
执行号:503. SQL> SELECT id,n_distinct,n_buckets FROM SYSSTATS where id=6518;

行号 ID N_DISTINCT N_BUCKETS


1 6518 0 0
2 6518 10 8

已用时间: 0.209(毫秒).
执行号:504.
SQL>
可以看到此时没有那么多的不同值可以放,系统自动将其平均放到了 8 个桶里。则此时可以 判断为等高直方图。但必定有的桶里的 NDV 相对少一些。

6 等分

这种情况也可以进一步看到:
SQL> stat 100 size 6 on h(x);
操作已执行
已用时间: 30.254(毫秒). 执行号:505.
SQL>
SQL> SELECT id,n_distinct,n_buckets FROM SYSSTATS where id=6518;

行号 ID N_DISTINCT N_BUCKETS


1 6518 0 0
2 6518 10 5

已用时间: 0.225(毫秒). 执行号:506.
SQL>
6 个桶不够用就均分使用了 5 个桶。

2 等分

或者还可以
SQL> stat 100 size 2 on h(x);
操作已执行
已用时间: 34.281(毫秒). 执行号:508.
SQL> SELECT id,n_distinct,n_buckets FROM SYSSTATS where id=6518;

行号 ID N_DISTINCT N_BUCKETS


1 6518 0 0
2 6518 10 2

已用时间: 0.170(毫秒). 执行号:509.
10 个 NDV 均分到 2 个桶里。

实验结论

我们可以在不同的场景里设置更适合的直方图统计信息。也给 dba 一个有趣的思路。

建议

此种设置后会导致初次进入环境的dba在不了解的情况下收集了并不合适的统计信息。 增加了业务中未知的风险。 
利用 dbms_stat 包进行收集: 

SQL> select sysdate from dual;

行号 SYSDATE


1 2022-12-16 15:04:17

已用时间: 0.667(毫秒). 执行号:517.
SQL> dbms_stats.gather_table_stats(ownname=>‘SYSDBA’,tabname=>‘H’,method_opt=>‘fo r all columns size repeat’,CASCADE=>true);
DMSQL 过程已成功完成
已用时间: 26.960(毫秒). 执行号:518.
SQL> SELECT id,n_distinct,n_buckets,last_gathered FROM SYSSTATS where id=6518;

行号 ID N_DISTINCT N_BUCKETS LAST_GATHERED


1 6518 0 0 2022-12-16 15:04:26.395000
2 6518 10 2 2022-12-16 15:04:26.411000

已用时间: 0.213(毫秒). 执行号:519.
SQL>

引申

COLUMN_STATS_SHOW

用此过程查看直方图统计信息类型很方便:
SQL> DBMS_STATS.COLUMN_STATS_SHOW(‘SYSDBA’,‘H’,‘X’); --用户、表名、列名
行号 NUM_DISTINCT LOW_VALUE HIGH_VALUE NUM_NULLS NUM_BUCKETS SAMPLE_SIZE ++HISTOGRAM ++



1 10 1 4.9E1 0 2 40000 HEIGHT BALANCED

已用时间: 1.353(毫秒). 执行号:512.
援引《DM8 系统管理员手册》:
通 过 DBMS_STATS 包 中 COLUMN_STATS_SHOW 、 TABLE_STATS_SHOW 和 INDEX_STATS_SHOW 查看表、列、索引的统计信息。只有用过 DBMS_STATS 包中 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 生成收集 操作之后才能查看到结果。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服