DM8数据库统计信息的导入导出

   关于统计信息的重要性,我觉着无需多言,本文仅讨论在一些迁移场景中对统计信息的迁移。因一些表的统计信息在重新收集统计信息时可能因环境不同或DBA对业务的了解不够造成统计信息收集发生偏差,最终造成SQL的执行计划是错误的。

这里仅讨论利用dexp和dimp对表数据的迁移。因dexp和dimp默认不会对源库中表的统计信息进行迁移。所以我们利用将目标表的统计信息导入到中间表,再利用dimp将此存储统计信息的中间表导入到目标库中的原理进行统计信息迁移。

预备环境student表:

SQL> CREATE TABLE STUDENT(
2   NAME VARCHAR(20),
3   AGE INT PRIMARY KEY,
4   SEX VARCHAR(10) CHECK (SEX IN ('MAIL','FEMAIL')), GRADE INT CHECK (GRADE IN (7,8,9)))
5   PARTITION BY LIST(GRADE)
6   SUBPARTITION BY LIST(SEX) SUBPARTITION TEMPLATE
7   (
8   SUBPARTITION Q1 VALUES('MAIL'),
9   SUBPARTITION Q2 VALUES('FEMAIL')
10  ),
11  SUBPARTITION BY RANGE(AGE) SUBPARTITION TEMPLATE
12  (
13  SUBPARTITION R1 VALUES LESS THAN (12),
14  SUBPARTITION R2 VALUES LESS THAN (15),
15  SUBPARTITION R3 VALUES LESS THAN (MAXVALUE)
16  )
17  (
18  PARTITION P1 VALUES (7),
19  PARTITION P2 VALUES (8),
20  PARTITION P3 VALUES (9)
21  );

警告: 列表分区未包含DEFAULT,可能无法定位到分区

操作已执行

已用时间: 47.376(毫秒). 执行号:512.

SQL> insert into student VALUES ('a',10,'MAIL',7);

影响行数 1


已用时间: 1.818(毫秒). 执行号:513.

SQL>

SQL> insert into student VALUES ('b',11,'MAIL',8);

影响行数 1


已用时间: 0.834(毫秒). 执行号:514.

SQL>

SQL> insert into student VALUES ('c',13,'MAIL',9);

影响行数 1


已用时间: 1.272(毫秒). 执行号:515.

SQL>

SQL> insert into student VALUES ('d',16,'MAIL',7);

影响行数 1


已用时间: 0.840(毫秒). 执行号:516.

SQL>

SQL> commit;

操作已执行

已用时间: 1.032(毫秒). 执行号:517.

统计信息的查看

SQL> SELECT SAMPLE_SIZE,LAST_ANALYZED FROM DBA_TABLES

行号     SAMPLE_SIZE LAST_ANALYZED
---------- ----------- -------------
1          NULL        NULL
SQL> select * from sysobjects where name = 'STUDENT'; --1541

行号     NAME    ID          SCHID       TYPE$  SUBTYPE$ PID         VERSION     CRTDATE                  
---------- ------- ----------- ----------- ------ -------- ----------- ----------- --------------------------
           INFO1       INFO2       INFO3                INFO4                INFO5    
           ----------- ----------- -------------------- -------------------- ----------
           INFO6                                              INFO7                INFO8      VALID
           -------------------------------------------------- -------------------- ---------- -----
1          STUDENT 1541        150994945   SCHOBJ UTAB     -1          0           2023-01-18 14:15:55.427000
           2097152     0           4503599627436043     0                    NULL
           0x000000000000000000000000000000000100000000000000 NULL                 NULL       Y


已用时间: 0.642(毫秒). 执行号:520.

SQL> select * from sysstats where id='1541';

未选定行


已用时间: 0.664(毫秒). 执行号:521.

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

--收集SYSDBA模式下所有对象的统计信息,包括索引

SQL> DBMS_STATS.GATHER_SCHEMA_STATS('SYSDBA',100,FALSE,'FOR ALL COLUMNS SIZE AUTO');

DMSQL 过程已成功完成

--收集
表上所有对象信息,包括索引

SQL> DBMS_STATS.GATHER_TABLE_STATS ('SYSDBA', 'STUDENT',NULL,100,FALSE,'FOR ALL COLUMNS SIZE AUTO');

DMSQL 过程已成功完成

已用时间: 200.984(毫秒). 执行号:524.

统计信息备份及导入

--创建统计信息存放表

SQL> call dbms_stats.CREATE_STAT_TABLE('SYSDBA', 'STUDENT_STAT');

DMSQL 过程已成功完成

已用时间: 8.807(毫秒). 执行号:526.

--查看统计信息存放表

SQL> SELECT * FROM STAT$_STUDENT_STAT;

未选定行

--导出统计信息

SQL> call dbms_stats.EXPORT_TABLE_STATS('SYSDBA', 'STUDENT', null, 'STUDENT_STAT', '1', TRUE);

DMSQL 过程已成功完成

已用时间: 92.940(毫秒). 执行号:528.

--再次查看统计信息存放表,表中出现了大量统计信息。此时统计信息中间表已经生成,将来将此表进行库间迁移即可达到统计信息迁移的目的。

SQL> SELECT count(*) FROM STAT$_STUDENT_STAT;


行号     COUNT(*)           

---------- --------------------

1          141


已用时间: 0.877(毫秒). 执行号:530.

SQL>

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

(结果略)

--新环境导入统计信息
call dbms_stats.import_table_stats('SYSDBA', 'STUDENT', null, 'STUDENT_STAT', '1', TRUE);

使用plsql块进行导出导入(实际环境中通常不是一张表,使用plsql块更加方便,可以批量导出一个模式下的所有表)。记住导出导入前先生成下统计信息中间表。也别忘记这个表的命名规则是:’STAT$_[你创建的中间表名]’,如:STAT$_STUDENT_STAT。

--导出
begin
        for i in
        (
TEST'
        )
        loop
TEST_STAT', '1', TRUE);
        END LOOP;
END;
--统计信息存放表的导入导出参考上一步
--导入
begin
        for i in
        (
TEST'
        )
        loop
TEST_STAT', '1', TRUE);
        END LOOP;
END;