注册
统计信息收集
技术分享/ 文章详情 /

统计信息收集

2026/08/14 95 0 0

统计信息收集

前言
在数据库运维中,统计信息的准确性直接影响SQL执行计划的优劣,进而决定查询性能。达梦数据库(DM8)提供了DBMS_STATS系统包来管理统计信息,本文将结合实际SQL脚本,详细介绍统计信息的收集方法与最佳实践。

一、DM8统计信息包概述

DBMS_STATS包是达梦数据库用于收集、管理和查看统计信息的核心工具。统计信息包括:

1、统计信息类型和说明:
表统计信息:行数、页数、已用页数
列统计信息:不同值数量、空值数量、最大值、最小值、直方图
索引统计信息:索引层级、叶子页数、不同键值数量

2、支持的统计信息收集对象:
普通表、分区表
列存储表(HUGE表)
索引

不支持:视图、物化视图、外部表、临时表

二、方法详解

  1. 收集表统计信息:GATHER_TABLE_STATS
PROCEDURE GATHER_TABLE_STATS( OWNNAME VARCHAR(128), TABNAME VARCHAR(128), PARTNAME VARCHAR(128) DEFAULT NULL, ESTIMATE_PERCENT DOUBLE DEFAULT ..., BLOCK_SAMPLE BOOLEAN DEFAULT FALSE, METHOD_OPT VARCHAR DEFAULT 'FOR ALL COLUMNS SIZE AUTO', DEGREE INT DEFAULT 1, GRANULARITY VARCHAR DEFAULT 'AUTO', CASCADE BOOLEAN DEFAULT TRUE, ... );
  • ESTIMATE_PERCENT 采样百分比(0-100) 大表用10-30,小表用100
  • BLOCK_SAMPLE TRUE按页采样,FALSE按行采样 大表建议TRUE,性能更好
  • METHOD_OPT 直方图策略 FOR ALL COLUMNS SIZE AUTO
  • CASCADE 是否同时收集索引统计信息 TRUE
  • DEGREE 并行度 默认1,可适当调大
  • GRANULARITY 分区表收集粒度 AUTO/GLOBAL/ALL
  1. 收集模式统计信息:GATHER_SCHEMA_STATS
BEGIN DBMS_STATS.GATHER_SCHEMA_STATS( OWNNAME => '模式名', ESTIMATE_PERCENT => 30, BLOCK_SAMPLE => TRUE, METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO', CASCADE => TRUE ); END; /
  1. 查看统计信息
-- 查看表统计信息 EXEC DBMS_STATS.TABLE_STATS_SHOW('模式名', '表名'); -- 查看列统计信息(含直方图) EXEC DBMS_STATS.COLUMN_STATS_SHOW('模式名', '表名', '列名'); -- 查看索引统计信息 EXEC DBMS_STATS.INDEX_STATS_SHOW('模式名', '索引名');
  1. 删除统计信息
-- 删除表统计信息 DBMS_STATS.DELETE_TABLE_STATS('模式名', '表名');

三、实战:批量收集统计信息
场景:收集指定模式下所有表的统计信息

-- 1. 查看表的最后收集时间,按数据量排序 SELECT last_analyzed "最后收集统计信息时间", 'dbms_stats.gather_table_stats('''||owner||''','''||table_name||''',null,100,TRUE,''FOR ALL COLUMNS SIZE AUTO'');' AS 收集语句, (table_rowcount(owner,table_name)) num FROM dba_tables WHERE owner IN ('模式名') -- 替换为实际模式名,大写 ORDER BY num; 执行结果示例 最后收集统计信息时间 收集语句 num 2026-07-15 10:30:00 dbms_stats.gather_table_stats('SYSDBA','ORDERS',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO'); 1,500,000 2026-07-14 08:20:00 dbms_stats.gather_table_stats('SYSDBA','PRODUCTS',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO'); 500,000 NULL dbms_stats.gather_table_stats('SYSDBA','LOG_TABLE',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO'); 50,000 实际收集脚本

– 方式一:逐个收集(适合有选择性地收集)

EXEC DBMS_STATS.GATHER_TABLE_STATS('SYSDBA','ORDERS',NULL,30,TRUE,'FOR ALL COLUMNS SIZE AUTO',4);

– 方式二:整个模式收集

BEGIN DBMS_STATS.GATHER_SCHEMA_STATS( OWNNAME => 'SYSDBA', ESTIMATE_PERCENT => 30, BLOCK_SAMPLE => TRUE, METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO', CASCADE => TRUE, DEGREE => 4 ); END; /

四、按列收集统计信息的场景

对于超大表,全部列都收集统计信息可能开销较大,可以针对特定列进行收集:

-- 生成按列收集统计信息的语句 SELECT 'stat 100 on "'||owner||'"."'||table_name||'"("'||column_name||'");' FROM DBA_TAB_COLUMNS WHERE owner='用户名' AND table_name='表名'; -- 实际使用示例(对于某张5000万行的订单表,只收集关键列) BEGIN DBMS_STATS.GATHER_TABLE_STATS('SYSDBA','ORDERS',NULL,20,TRUE,'FOR COLUMNS ORDER_ID SIZE 100, CUSTOMER_ID SIZE 100, ORDER_DATE SIZE AUTO'); END; /

五、实践建议

  1. 收集策略
  • 表大小 采样率 BLOCK_SAMPLE 直方图策略 频率
  • 小表(<10万行) 100% FALSE SIZE AUTO 每周
  • 中表(10万-1000万) 50% FALSE SIZE AUTO 每周
  • 大表(>1000万行) 10-30% TRUE SIZE AUTO 每天/根据变更率
  • 分区表 10-20% TRUE GLOBAL+PARTITION 根据分区变更
  1. 统计信息状态
-- 查看哪些表统计信息过时 SELECT owner, table_name, stale_stats FROM dba_tab_statistics WHERE stale_stats = 'YES';
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服