注册
自动收集统计信息(分区表配置为增量收集)
技术分享/ 文章详情 /

自动收集统计信息(分区表配置为增量收集)

wuran 2025/12/12 56 0 0

定时收集统计信息,为优化器提供准确的数据分布特征,可保证生成高效执行计划,避免性能问题。数据量较大的场景,更新统计信息耗时较久,建议对关键分区表启用增量收集,其他表用自动收集,平衡性能与准确性。
AUTO_STAT_OBJ参数控制统计信息的自动监控行为,0表示禁用自动监控,1表示监控所有用户表,2表示仅监控配置,未配置的表不触发自动收集。推荐AUTO_STAT_OBJ=2,精准控制统计信息收集范围,避免对非核心表(如日志表、临时表)的无意义监控,降低CPU/IO消耗。

一、单表自动收集

适合数据量小、变化均匀的场景,保证统计信息全面性。

1、开启自动收集功能。
call sp_set_para_value(1,'AUTO_STAT_OBJ',2);--对特定表进行收集
2、初始化测试表,并插入100条数据
create table T(id int,name varchar2(20));
create index idx_id_name on T(id,name);
begin
 for i in 1..100 loop
 	insert into T values(i,'name'||i);
 end loop;
end;
commit;
3、收集统计信息
SP_TAB_STAT_INIT('SYSDBA','T');
SP_STAT_ON_TABLE_COLS('SYSDBA','T',100);
SP_TAB_INDEX_STAT_INIT('SYSDBA','T',100);
4、查看统计信息情况  --数据量100
--SELECT SF_GET_TABLENAME_BY_ID(ID) as Table_name,ID,COLID,T_FLAG,T_TOTAL,N_SAMPLE,N_DISTINCT,N_NULL,LAST_GATHERED FROM SYSSTATS;
--SELECT * FROM SYSSTATTABLEIDU WHERE ID=(select id from sysobjects where name='T');--未开启自动收集所以返回空
select id,colid,t_flag,t_total,n_sample,n_distinct,last_gathered,* from sysstats where id=(select id from sys.sysobjects where name = 'T');
5、指定T表监控数据变化率为10%
DBMS_STATS.SET_TABLE_PREFS('SYSDBA','T','STALE_PERCENT',10);
6、设置触发收集采样率为100%
dbms_stats.set_table_prefs('SYSDBA','T','ESTIMATE_PERCENT',100);
7、设置统计信息收集级别 0表示收集所有统计信息(表、列、索引) 1表示仅收集表和列的统计信息(忽略索引) 2表示仅收集表和索引的统计信息(忽略列) 3(1+2):收集表、列、索引的统计信息 5(1+4):收集表和索引涉及列的统计信息 
dbms_stats.set_table_prefs('SYSDBA', 'T', 'AUTO_GRANULARITY',0);
8、检查表T是否配置了自动收集
--若返回记录且 `STALE_PERCENT > 0`(如 `10` 表示10%变更阈值),则该表已启用自动收集。
SELECT T1.NAME AS TABLE_NAME,T2.PNAME AS CONFIG_NAME,T2.VALUENUM AS STALE_PERCENT
FROM SYSOBJECTS T1
     JOIN SYSSTATPREFS T2 ON T1.ID = T2.ID
     WHERE T1.SUBTYPE$ = 'UTAB' AND T1.NAME = 'T' 
         AND T1.SCHID = (select id from SYSOBJECTS where name='SYSDBA' and type$='SCH')
         AND T2.PNAME = 'STALE_PERCENT';
9、向表T插入30条数据,变化率超过10%
begin
 	for i in 1..30 loop
 		insert into T values(i,'name'||i);
 	end loop;
 end;
 commit;
10、查询是否触发自动收集统计信息
select id,colid,t_flag,t_total,n_sample,n_distinct,last_gathered,* from sysstats where id=(select id from sys.sysobjects where name = 'T');
SELECT * FROM SYSSTATTABLEIDU WHERE ID=(select id from sysobjects where name='T');--针对自动收集统计信息功能,记录用户表统计信息监控数据
--SELECT SF_GET_TABLENAME_BY_ID(ID) as Table_name,ID,COLID,T_FLAG,T_TOTAL,N_SAMPLE,N_DISTINCT,N_NULL,LAST_GATHERED FROM SYSSTATS;
select count(*) from T;--130
11、设置调度 从2021/11/18开始,每天1点55分开始,每隔30分钟执行一次统计信息收集工作,如果表T的变化数据超过10%,就会触发。默认值:`1439`(表示当天仅执行一次)
SP_CREATE_AUTO_STAT_TRIGGER(1, 1, 0, 30,'01:55', '2021/11/18',3600, 1);
12、向表T插入50条数据,变化率超过10%
begin
 	for i in 1..50 loop
 		insert into T values(i,'name'||i);
 	end loop;
 end;
 commit;
13、30分钟后检查是否自动收集了统计信息
SELECT * FROM SYSSTATTABLEIDU WHERE ID=(select id from sysobjects where name='T');
select id,colid,t_flag,t_total,n_sample,n_distinct,last_gathered,* from sysstats;--表、列和索引都自动收集了统计信息

二、分区表增量收集

针对海量数据表,通过局部扫描显著提升效率并降低资源开销,是分区表优化的首选方案。
开启增量收集统计信息(INCREMENTAL=TRUE)前,强烈建议先手动执行一次全量统计信息收集。
增量收集仅针对数据变动超过阈值的分区子表。若从未收集过全量统计信息,系统无法识别哪些分区需要更新,导致增量收集失效。

1、开启自动收集功能。
call sp_set_para_value(1,'AUTO_STAT_OBJ',2);--对特定表进行收集
2、初始化测试表,并插入100条数据
CREATE TABLE T_RANGE (
	A INT,
	B VARCHAR,
	C DATETIME
)
PARTITION BY RANGE(C)
(
	PARTITION P1 VALUES LESS THAN ('2021-09-01'),--<2021-09-01
	PARTITION P2 VALUES LESS THAN ('2021-10-01'),--<=2021-09-30 <2021-10-01
	PARTITION P3 VALUES LESS THAN ('2021-11-01'),
	PARTITION P4 VALUES LESS THAN ('2021-12-01'),
	PARTITION P5 VALUES EQU OR LESS THAN(MAXVALUE)  --加maxvalue就不能再新建分区了,会报错:-2730: 第1 行附近出现错误: 范围分区值非递增,但是可以split   一级分区支持split,但是二级分区不支持split,支持add 语法就不支持split subparition 但别的库支持。。。
);
insert into T_RANGE select DBMS_RANDOM.VALUE(0,365),dbms_random.string('X',10),'2021-09-02' from dual connect by level <= 100;
commit;
select count(*) from T_RANGE;--100
select * from T_RANGE;--100
3、收集统计信息
SP_TAB_STAT_INIT('SYSDBA','T_RANGE');
SP_STAT_ON_TABLE_COLS('SYSDBA','T_RANGE',100);
SP_TAB_INDEX_STAT_INIT('SYSDBA','T_RANGE',100);
4、查看统计信息情况  --数据量100
--SELECT SF_GET_TABLENAME_BY_ID(ID) as Table_name,ID,COLID,T_FLAG,T_TOTAL,N_SAMPLE,N_DISTINCT,N_NULL,LAST_GATHERED FROM SYSSTATS;
--SELECT * FROM SYSSTATTABLEIDU WHERE ID=(select id from sysobjects where name='T');--未开启自动收集所以返回空
select id,colid,t_flag,t_total,n_sample,n_distinct,last_gathered,* from sysstats where id=(select id from sys.sysobjects where name = 'T');
5、设置为INCREMENTAL 增量收集
--设置增量收集 为false的话不做增量收集,但是数据变动达到该表对应的stale percent还是会触发自动收集(通过普通方式收集统计信息)
dbms_stats.set_table_prefs('SYSDBA', 'T_RANGE', 'INCREMENTAL','TRUE');
6、指定T表监控数据变化率为10%
DBMS_STATS.SET_TABLE_PREFS('SYSDBA','T_RANGE','STALE_PERCENT',10);
7、设置触发收集采样率为100%
dbms_stats.set_table_prefs('SYSDBA','T_RANGE','ESTIMATE_PERCENT',100);
8、设置统计信息收集级别 0表示收集所有统计信息(表、列、索引) 1表示仅收集表和列的统计信息(忽略索引) 2表示仅收集表和索引的统计信息(忽略列) 3(1+2):收集表、列、索引的统计信息 5(1+4):收集表和索引涉及列的统计信息 
dbms_stats.set_table_prefs('SYSDBA', 'T_RANGE', 'AUTO_GRANULARITY',0);
9、设置并行度
dbms_stats.set_table_prefs('SYSDBA', 'T_RANGE', 'ESTIMATE_PERCENT',16);
10、检查表T是否配置了自动收集
--若返回记录且 `STALE_PERCENT > 0`(如 `10` 表示10%变更阈值),则该表已启用自动收集。
SELECT T1.NAME AS TABLE_NAME,T2.PNAME AS CONFIG_NAME,T2.VALUENUM AS STALE_PERCENT
FROM SYSOBJECTS T1
     JOIN SYSSTATPREFS T2 ON T1.ID = T2.ID
     WHERE T1.SUBTYPE$ = 'UTAB' AND T1.NAME = 'T_RANGE' 
         AND T1.SCHID = (select id from SYSOBJECTS where name='SYSDBA' and type$='SCH')
         AND T2.PNAME = 'STALE_PERCENT';
11、向表T插入100条数据,变化率超过10%
insert into T_RANGE select DBMS_RANDOM.VALUE(0,365),dbms_random.string('X',10),'2021-10-02' from dual connect by level &lt;= 100;
commit;
12、查询是否触发自动收集统计信息
select id,colid,t_flag,t_total,n_sample,n_distinct,last_gathered,* from sysstats where id=(select id from sys.sysobjects where name = 'T_RANGE');
SELECT * FROM SYSSTATTABLEIDU WHERE ID=(select id from sysobjects where name='T_RANGE');--针对自动收集统计信息功能,记录用户表统计信息监控数据
--SELECT SF_GET_TABLENAME_BY_ID(ID) as Table_name,ID,COLID,T_FLAG,T_TOTAL,N_SAMPLE,N_DISTINCT,N_NULL,LAST_GATHERED FROM SYSSTATS;
select count(*) from T_RANGE;--130
13、设置调度 从2021/11/18开始,每天1点55分开始,每隔5分钟执行一次统计信息收集工作,如果表T的变化数据超过10%,就会触发。默认值:`1439`(表示当天仅执行一次)
SP_CREATE_AUTO_STAT_TRIGGER(1, 1, 0, 5,'01:55', '2021/11/18',3600, 1);
14、向表T插入100条数据,变化率超过10%
insert into T_RANGE select DBMS_RANDOM.VALUE(0,365),dbms_random.string('X',10),'2021-11-02' from dual connect by level &lt;= 100;
commit;
15、5分钟后检查是否自动收集了统计信息
SELECT * FROM SYSSTATTABLEIDU WHERE ID=(select id from sysobjects where name='T_RANGE');
select id,colid,t_flag,t_total,n_sample,n_distinct,last_gathered,* from sysstats where id=(select id from sys.sysobjects where name = 'T_RANGE');--表、列和索引都自动收集了统计信息
16、配置监控增量收集统计信息
--1)创建表用以保存自动收集过程的相关信息 
create table AUTO_STAT_INFO(
	task_id INT,
	total_stat INT,
	table_id INT,
	current_gather_tab_id INT,
	success_stat INT,
	fail_stat INT,
	task_start_time DATETIME, 
	task_end_time DATETIME,
	gather_tbl_start_time DATETIME,
	gather_tbl_end_time DATETIME);
--2)创建确定的过程SYSDBA.GET_AUTO_STAT_INFO_FUNC,用以接收服务器在自动收集统计信息时的相关信息
CREATE OR REPLACE PROCEDURE  SYSDBA.GET_AUTO_STAT_INFO_FUNC(
	task_id INT,
	total_stat INT,
	table_id INT,
	SCHEMA_NAME VARCHAR(100),
	TABLE_NAME VARCHAR(100),
	current_gather_tab_id INT,
	current_gather_schema_name varchar(100),
	current_gather_tab_name varchar(100),
	success_stat INT,
	fail_stat INT,
	task_start_time DATETIME, 
	task_end_time DATETIME,
	gather_tbl_start_time DATETIME,
	gather_tbl_end_time DATETIME) as
BEGIN
    INSERT INTO AUTO_STAT_INFO 
    VALUES(task_id,
    	   total_stat,
    	   table_id,
    	   current_gather_tab_id,
    	   success_stat,
    	   fail_stat,
    	   task_start_time,
    	   task_end_time,
    	   gather_tbl_start_time,
    	   gather_tbl_end_time);
    commit;
EXCEPTION
    WHEN OTHERS THEN
        NULL;
END;
17、向表T插入100条数据,变化率超过10%
insert into T_RANGE select DBMS_RANDOM.VALUE(0,365),dbms_random.string('X',10),'2021-12-02' from dual connect by level &lt;= 100;
commit;
select count(*) from T_RANGE;--400
18、查看自动收集统计信息任务相关的配置和状态信息。
select * from AUTO_STAT_INFO;
如果表AUTO_STAT_INFO内容始终为空,查看v$runtime_err_history是否有相关报错。如果报错:[GET_AUTO_STAT_INFO_FUNC]调用参数不兼容或者不匹配,说明存储过程配置有问题。
auto_stat_info_func这个系统过程的参数个数和类型要跟管理员使用手册上定义的保持一致(参数名可以自定义,字符类型的长度也可以自定义,最好定义的长一点,比当前库中的表名长,否则写不进去),监控表,auto_stat_info,表列多几个少几个没关系。
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服