注册
浅谈 DM8 统计信息维护与管理
专栏/技术分享/ 文章详情 /

浅谈 DM8 统计信息维护与管理

FoxZzz 2026/09/30 288 0 0
摘要

在数据库性能优化过程中,执行计划是否合理,很大程度上取决于优化器对数据规模和数据分布的判断是否准确。DM8 优化器在进行访问路径选择、连接顺序选择以及连接算法选择时,需要依赖对象统计信息计算不同执行计划的代价。如果统计信息缺失、长期未更新或者无法准确描述当前数据分布,即使 SQL 本身和索引设计没有发生变化,也可能因为基数估算偏差而产生不合理的执行计划。
因此,统计信息维护不能简单理解为“定期执行一次统计信息收集”,而应该建立一套完整的管理过程,包括统计信息的收集、检查、更新时机判断、采样比例控制、分区对象处理以及统计信息变更后的执行计划验证。

1. 为什么要收集统计信息

DM8 使用基于代价的优化方式生成执行计划。优化器在比较多个候选执行路径时,需要估算每一个执行节点可能处理的数据量以及对应的资源消耗,而统计信息就是完成这些估算的重要基础。
例如下面的查询:

SELECT *
FROM T_ORDER
WHERE STATUS = 'NEW';

优化器需要判断 STATUS=‘NEW’ 大约能够返回多少行。如果表中共有 1000 万行,而 NEW 状态只有几千行,那么通过索引访问通常具有较大的优势;如果 NEW 占到了总数据量的大部分,全表扫描可能反而更加合理。
这意味着优化器不仅需要知道表中大约存在多少行数据,还需要知道列有多少个不同值、NULL 值数量、最大值和最小值以及数据是否存在明显倾斜。
如果这些信息与当前数据严重不一致,就可能形成如下问题链路:

统计信息失真——>选择率估算错误——>Cardinality 基数估算错误——>Cost 计算发生偏差——>访问路径或连接顺序选择错误——>SQL 性能下降

值得注意的是,统计信息维护的目标并不是单纯追求“最新”,而是保证统计信息能够尽可能准确地描述 SQL 执行时的数据状态。

2. 如何收集统计信息

DM8 的统计信息可以分为静态统计信息和动态统计信息。
静态统计信息提前收集并保存到系统表中,在后续 SQL 优化时直接使用;动态统计信息则是在生成执行计划期间临时进行数据采样。由于动态采样本身发生在 SQL 优化阶段,会增加解析和优化时间,因此生产系统应以静态统计信息维护为主,动态采样作为补充。

2.1 使用 DBMS_STATS

DM8 提供 DBMS_STATS 系统包进行统计信息管理。
最常见的是表级收集:

CALL DBMS_STATS.GATHER_TABLE_STATS(
    'SYSDBA',
    'T_ORDER'
);

GATHER_TABLE_STATS 可以收集表、列以及表上索引的相关统计信息。DM8 官方接口中提供了 ESTIMATE_PERCENT、METHOD_OPT、DEGREE、GRANULARITY、CASCADE 等参数,可以分别控制采样率、列统计方式、并行度、分区粒度以及是否同步处理索引统计信息。

参数 作用
OWNNAME 模式名
TABNAME 表名
ESTIMATE_PERCENT 采样比例,范围 0~100
BLOCK_SAMPLE TRUE 按数据页采样,FALSE 按数据行采样
METHOD_OPT 控制列统计信息及直方图收集方式
DEGREE 并行度
CASCADE 是否同时处理索引统计信息

也可以进行模式级统计:

CALL DBMS_STATS.GATHER_SCHEMA_STATS('APP');

对于数据库初始化或者特殊维护场景,还可以使用 DM8 提供的统计信息存储过程。

2.2 使用 STAT

除了 DBMS_STATS,DM8 还支持 STAT 语句。
例如按照 30% 的比例对列进行统计:

STAT 30 ON SYS.SYSOBJECTS(ID);

2.3 自动统计信息收集

在正式生产实践中,一般不使用自动统计信息收集,建议采用job调度制定统计信息维护任务,对应复杂系统建议使用statcmd工具维护

对于生产数据库,如果完全依靠 DBA 手工判断所有对象是否需要重新收集统计信息,维护成本会非常高。
DM8 可以通过:AUTO_STAT_OBJ 监控对象的数据变化,并结合自动统计信息任务进行维护。当 AUTO_STAT_OBJ 设置为 1 或 2 时,可以使用 SP_CREATE_AUTO_STAT_TRIGGER 实现自动统计信息收集。
同时,DM8 提供:STALE_PERCENT 用于描述对象数据变化达到什么程度之后可以认为统计信息已经陈旧。

3. 统计信息包含什么内容

DM8 优化器使用的对象统计信息主要可以分为表统计信息、列统计信息和索引统计信息。
3.1 表统计信息
表统计信息主要描述对象整体规模,例如:

表总行数
数据页数量
已经使用的数据页数量

表统计信息能够帮助优化器首先判断一个对象是几十行的小表,还是数千万甚至数亿行的大表。
3.2 列统计信息
列统计信息更加直接地影响谓词选择率估算,通常包括:

不同值数量 NDV
NULL 值数量
最大值
最小值
采样数量
直方图信息

例如:

SELECT *
FROM T_ORDER
WHERE STATUS = 'NEW';

仅仅知道 T_ORDER 有 1000 万行并不足以决定应该采用何种访问路径。优化器还需要知道 STATUS 有多少个不同值以及不同值之间的数据分布情况。
3.3 索引统计信息
索引统计信息描述索引本身的数据结构和数据分布,例如索引层级、叶子节点数量、不同键值数量等。
DM8 可以通过 DBMS_STATS 提供的 SHOW 接口查看统计信息,例如:

CALL DBMS_STATS.TABLE_STATS_SHOW(
    'SYSDBA',
    'T_ORDER'
);

CALL DBMS_STATS.COLUMN_STATS_SHOW(
    'SYSDBA',
    'T_ORDER',
    'STATUS'
);

CALL DBMS_STATS.INDEX_STATS_SHOW(
    'SYSDBA',
    'IDX_ORDER_STATUS'
);

4. 什么时候收集统计信息

统计信息维护最关键的问题之一并不是“怎么收集”,而是“什么时候应该重新收集”。
对于一个数据基本没有发生变化的表,即使统计信息已经存在半年,也不一定意味着它已经失效。相反,一个昨天刚刚收集统计信息的表,如果今天完成了一次大规模数据装载,其统计信息可能已经不能描述当前数据状态。
比较典型的统计信息更新场景包括首次完成数据初始化、大批量 INSERT、大批量 DELETE、大规模 UPDATE、ETL 装载完成、新增大量分区数据以及数据迁移完成等。
DM8 提供:

SYSSTATTABLEIDU
V$AUTO_STAT_TABLE_IDU

用于辅助记录和观察表的数据变化情况。

V$AUTO_STAT_TABLE_IDU 可以记录插入、删除和更新的数据量,但只有 AUTO_STAT_OBJ=1 或 2 时才进行相关统计。

5. 其他类型的统计信息

仅依赖普通的单列统计信息,并不能解决所有基数估算问题。
一个典型场景是多个列之间存在明显的业务相关性。
例如:

SELECT *
FROM T_ADDRESS
WHERE PROVINCE = '浙江省'
  AND CITY = '杭州市';

如果优化器分别统计:

PROVINCE:34 个不同值
CITY:500 个不同值

但不知道 PROVINCE 和 CITY 之间存在明显关联,那么按照两个完全独立的条件计算选择率,就可能低估或者高估最终返回的数据量。DM8 支持多维统计信息,并通过 SYSMSTATS 等系统信息保存相关内容。

另一个重要内容是直方图。普通 NDV 统计更接近于假设:不同值的数据分布相对均匀。但生产数据库中的数据通常并不均匀。例如订单状态:

FINISHED    9,500,000
CANCEL        300,000
NEW            20,000
ERROR             500

如果优化器仅知道 STATUS 有 4 个不同值,很容易错误估算 STATUS=‘ERROR’ 的数据量。此时直方图能够进一步描述不同值的数据分布,从而改善基数估算。

6. 统计信息采集性能

数据库必须读取对象中的部分甚至全部数据,才能建立统计信息,因此会产生 CPU、I/O 和缓存资源消耗。对于数十亿行的大表,如果不区分对象大小统一执行 100% 全量统计,很容易让统计信息维护本身成为系统负载来源。
对于小表,可以使用较高采样比例;对于超大表,则需要综合考虑统计准确性与统计维护时间,并行收集也同样如此。
例如:

DBMS_STATS.GATHER_TABLE_STATS(
    OWNNAME          => 'APP',
    TABNAME          => 'T_ORDER',
    ESTIMATE_PERCENT => 30,
    DEGREE           => 8
);

增加并行度能够缩短单个大型对象的统计时间,但如果同时对几十张大表设置较高并行度,就可能形成大量并发扫描。

7. 无需收集统计信息的情况

并不是所有对象都需要频繁维护统计信息。数据量变化非常剧烈的表、中间表以及一次写入一次读取后就被清空的 ETL 对象,对这些表反复收集统计信息可能本身就没有太大价值。
例如一张表在装载后执行一次耗时 10 分钟的统计信息收集,而半小时之后整张表又被清空,这次统计信息维护本身的收益就值得重新评估。

8. 总结

对于长期稳定运行的 DM8 数据库,比较合理的统计信息体系应该以静态统计信息为主、自动监控为基础、动态采样为补充,并通过统计信息备份与执行计划验证控制变更风险。DM8 官方文档明确支持静态/动态收集、DBMS_STATS、STAT、自动统计以及对象变化监控,因此可以围绕这些机制建立生产环境统计信息维护体系。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服