前言:
数据库技术有很多,谈到数据库的核心技术,我觉得优化器尤为重要。在CBO时代,我们已经不用再关注驱动表的问题,动态采样也已经渐渐退出舞台,影响优化器代价的统计信息变得十分重要。

一、什么是统计信息?
简单来说,统计信息记录了数据库中表及索引的分布情况,并根据数据分布特征生成频率直方图或者等高直方图。

二、统计信息是如何影响CBO的呢?
影响CBO的因素有很多,在我看来,数据访问路径占了其中的90%以上,其余的为CPU及操作系统内核参数。统计信息记录了selectivity、聚簇因子、表的行数等信息,它让CBO理解数据,并以最好的路径进行访问。

三、统计信息为什么需要导入导出?
在数据量比较大的项目中,收集统计信息的时间有时候比数据迁移的时间还要长,这是很常见的情况。而停机时间要求都比较严格,这种情况下,我们就可以提前导出统计信息,并在完成数据迁移之后进行导入,节约时间。
四、统计信息的查看

--dba_tables可以看到表的统计信息
SELECT SAMPLE_SIZE,LAST_ANALYZED FROM DBA_TABLES WHERE table_name = 'T1';
--sysstats(直方图)结合表ID和对象ID可以看到表或者列和索引的统计信息
select * from sysobjects where name = 'T1'; --1495
select * from sysstats where id='1495';

五、统计信息收集(使用了dbms_stats包,参考DM8系统包使用手册)

--收集TEST模式下所有对象的统计信息,包括索引
DBMS_STATS.GATHER_SCHEMA_STATS('TEST',100,FALSE,'FOR ALL COLUMNS SIZE AUTO');
--收集T1表上所有对象信息,包括索引
DBMS_STATS.GATHER_TABLE_STATS ('TEST', 'T1',NULL,100,FALSE,'FOR ALL COLUMNS SIZE AUTO');

六、统计信息备份及导入

--创建统计信息存放表 
call dbms_stats.CREATE_STAT_TABLE('TEST', 'TEST_STAT');

--查看统计信息存放表
SELECT * FROM STAT$_TEST_STAT;

--导出统计信息
call dbms_stats.EXPORT_TABLE_STATS('TEST', 'T1', null, 'TEST_STAT', '1', TRUE);
--再次查看统计信息存放表
SELECT * FROM STAT$_TEST_STAT;

--使用达梦数据库dexp/dimp工具或者dts工具进行统计信息表存放表的导入导出或者迁移(这里选择dexp/dimp)
--dexp导出
./dexp userid=TEST/123456789:5236 file=/data/stat.dmp log=/data/stat.log tables='STAT$_TEST_STAT'

--dimp导入新环境
./dimp userid=TEST/123456789:5236 file=/data/stat.dmp log=/data/stat.log tables='STAT$_TEST_STAT'

--新环境导入统计信息
call dbms_stats.import_table_stats('TEST', 'T1', null, 'TEST_STAT', '1', TRUE);

七、使用plsql块进行导出导入(实际环境中通常不是一张表,使用plsql块更加方便,可以批量导出一个模式下的所有表)

--导出
begin
        for i in
        (
                select a.owner, a.table_name from all_tables a where a.owner='TEST'
        )
        loop
                call dbms_stats.export_table_stats(i.owner, i.table_name, null, 'TEST_STAT', '1', TRUE);
        END LOOP;
END;
--统计信息存放表的导入导出参考上一步
--导入
begin
        for i in
        (
                select a.owner, a.table_name from all_tables a where a.owner='TEST'
        )
        loop
                call dbms_stats.import_table_stats(i.owner, i.table_name, null, 'TEST_STAT', '1', TRUE);
        END LOOP;
END;

结语
统计信息让CBO更好的理解数据,让CBO产生好的访问路径,而统计信息导入导出对于节约时间,减少停机窗口,不失为一种好的方法。