实际工作中有些项目遇到一些表数据较大,收集统计信息是件棘手的事,因为经常在业务不忙时运行 DBMS_STATS.GATHER_SCHEMA_STATS('用户名',100,TRUE,'FOR ALL COLUMNS SIZE AUTO') 收集一个模式的统计信息时,耗时很久甚至需要好几天时间。
另外,以上SQL只能使用一个CPU,在夜晚进行统计时数据库一般处于较闲的状态,不能合理使用CPU资源。所以可以采用多会话的方式来收集。
登录SYSDBA用户,先创建系统包,
SP_CREATE_SYSTEM_PACKAGES(1);
再创建统计信息记录表如下:
CREATE TABLE DB_TAB_STATS(TABLE_NAME VARCHAR2(100),STAT_FLAG VARCHAR2(5));
初始化统计信息记录表,如目标是用户DMHR下的所有表
INSERT INTO DB_TAB_STATS(TABLE_NAME) SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER = DMTEST;
UPDATE DB_TAB_STATS SET STAT_FLAG = 0;
COMMIT;
--收集统计信息
BEGIN
FOR TB IN (SELECT ROWID,TABLE_NAME FROM DB_TAB_STATS WHERE ROWID<=1000)
LOOP
DBMS_STATS.GATHER_TABLE_STATS('DMTEST',TB.TABLE_NAME,NULL,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
UPDATE DB_TAB_STATS SET STAT_FLAG = 1 WHERE TABLE_NAME = TB.TABLE_NAME;
COMMIT;
END LOOP;
END;
用ROWID可以将用户表分成多个区间进行收集。比如有20000张表需要收集,分成15000、500110000、1000115000和1500120000来收集的话,就能利用到4个CPU,提高收集统计信息的效率。如果发生报错而中断的情况,能根据表中的STAT_FLAG列来检查进度,以便于下次继续收集。
另一种方式:
DBMS_STATS.GATHER_SCHEMA_STATS(‘模式名’,100,TRUE,‘FOR ALL INDEXED SIZE AUTO’,8);
这里8为并行度8;详细解释见官方包手册。可以批量拼接出语句切块并行执行。更新统计信息时需测试验证,不管哪种方式,需找到合适的并行度,以免影响现有业务使用。
如上两种方式仅供参考,以现场环境为主,需测试验证不影响现有业务后在使用。
文章
阅读量
获赞