Oracle统计信息的导出导入测试示例详解

背景:

有时我们会希望可以对Oracle的统计信息整体进行导出导入。比如在数据库迁移前后,希望统计信息保持不变;又比如想对统计信息重新进行收集,但是担心重新收集的结果反而引发性能问题,想先保存当前的统计信息,这样即使重新收集后效果不好还可以导入之前的统计信息。

Oracle提供给我们一些方法,比较常用的粒度有两种:

  • schema级别统计信息的导出导入
    通过调用DBMS_STATS.EXPORT_SCHEMA_STATS和DBMS_STATS.IMPORT_SCHEMA_STATS来进行。
  • database级别统计信息的导出导入
    通过调用DBMS_STATS.EXPORT_DATABASE_STATS和DBMS_STATS.IMPORT_DATABASE_STATS来进行。

统计信息存放的表可以通过DBMS_STATS.CREATE_STAT_TABLE和DBMS_STATS.DROP_STAT_TABLE来进行创建或是删除。

1.示例schema级别统计信息的导出导入

比如我将JINGYU这个schema下所有的统计信息进行导出导入:

--源端统计信息导出:
begin
 DBMS_STATS.CREATE_STAT_TABLE('SYSTEM','JINGYU_STATS_20181217');
 DBMS_STATS.EXPORT_SCHEMA_STATS(OWNNAME => 'JINGYU', STATTAB => 'JINGYU_STATS_20181217', STATOWN => 'SYSTEM');
end;
/
expdp \'/ as sysdba\' directory=xtts dumpfile=stats_jingyu.dmp logfile=stats_jingyu.log tables=system.jingyu_stats_20181217

--目标端统计信息导入:
impdp \'/ as sysdba\' directory=xtts dumpfile=stats_jingyu.dmp logfile=stats_jingyu.log cluster=n
exec DBMS_STATS.IMPORT_SCHEMA_STATS (OWNNAME => 'JINGYU', STATTAB => 'JINGYU_STATS_20181217', STATOWN => 'SYSTEM');

--删除存放统计信息的表(根据实际需要选择性执行):
exec DBMS_STATS.DROP_STAT_TABLE ('SYSTEM','JINGYU_STATS_20181217');

2.示例database级别统计信息的导出导入

如果想将数据库所有统计信息进行导出导入,方法非常类似,使用对应的过程:

--源端统计信息导出:
begin
 DBMS_STATS.CREATE_STAT_TABLE('SYSTEM','DB_STATS_20181217');
 DBMS_STATS.EXPORT_DATABASE_STATS(STATTAB => 'DB_STATS_20181217', STATOWN => 'SYSTEM');
end;
/
expdp \'/ as sysdba\' directory=xtts dumpfile=stats.dmp logfile=stats.log tables=system.db_stats_20181217

--目标端统计信息导入:
impdp \'/ as sysdba\' directory=xtts dumpfile=stats.dmp logfile=stats.log cluster=n
exec DBMS_STATS.IMPORT_DATABASE_STATS (STATTAB => 'DB_STATS_20181217', STATOWN => 'SYSTEM');

--删除存放统计信息的表(根据实际需要选择性执行):
exec DBMS_STATS.DROP_STAT_TABLE ('SYSTEM','DB_STATS_20181217');

3.验证统计信息导出导入效果

以数据库级别统计信息的导出导入为例,验证下实际的效果:

目前数据库JINGYU用户下各表在统计信息记录数:

SYS@orcl> select owner, table_name, NUM_ROWS from dba_tables where owner = 'JINGYU';

OWNER       TABLE_NAME      NUM_ROWS
------------------------------ ------------------------------ ----------
JINGYU       TEST        100708
JINGYU       ASH_TMP        226

此时按照之前的步骤导出数据库的统计信息,步骤不再赘述。

然后在某一张表插入数据,重新收集该表的统计信息:

SYS@orcl> insert into jingyu.ash_tmp select * from jingyu.ash_tmp;
SYS@orcl> commit;

SYS@orcl> exec dbms_stats.gather_table_stats('JINGYU','ASH_TMP');

PL/SQL procedure successfully completed.

再去查询统计信息记录的该表行数:

SYS@orcl> select owner, table_name, num_rows from dba_tables where owner='JINGYU';

OWNER       TABLE_NAME      NUM_ROWS
------------------------------ ------------------------------ ----------
JINGYU       TEST        100708
JINGYU       ASH_TMP        452

此时按照之前的步骤导入数据库的统计信息,步骤不再赘述。

再去查询统计信息记录的该表行数,已经恢复到当时的导出时刻:

SYS@orcl> select owner, table_name, num_rows from dba_tables where owner='JINGYU';

OWNER       TABLE_NAME      NUM_ROWS
------------------------------ ------------------------------ ----------
JINGYU       TEST        100708
JINGYU       ASH_TMP        226

SYS@orcl> 

另外,需要注意如果统计信息导入的目标环境,数据库版本比源环境高(多发生在数据库升级场景),导入统计信息时会遇到下面这样的错误:

ERROR at line 1:
ORA-20002: Version of statistics table SYSTEM.DB_STATS_20181217 is too old.
Please try upgrading it with dbms_stats.upgrade_stat_table
ORA-06512: at "SYS.DBMS_STATS", line 11648
ORA-06512: at "SYS.DBMS_STATS", line 11665
ORA-06512: at "SYS.DBMS_STATS", line 12800
ORA-06512: at line 1

这时只需要按照提示执行下 dbms_stats.upgrade_stat_table

exec dbms_stats.upgrade_stat_table('SYSTEM','db_stats_20181217');

再尝试导入统计信息就可以成功了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • ORACLE中关于表的一些特殊查询语句

    1: 如何判断字段的值里面:那些数据包含小写字母或大小字母 判断字段NAME的值里面有小写字母的记录 方式1: SELECT NAME FROM TEST WHERE regexp_like(NAME,'[[:lower:]]'); 方式2 SELECT NAME FROM TEST WHERE regexp_like(NAME,'[a-z]'); 判断字段NAME的值里面有大写字母的记录 方式1: SELECT NAME FROM TEST WHERE regexp_like(NAME,'[[

  • Oracle数据库中 call 和 exec的区别

    今天发现了一个小东西,觉得很有意思,查找了一些资料,跟大家分享一下: 在sqlplus中: 在第三方提供的工具(如:plsqldev) 总结: exec是sqlplus的命令,只能在sqlplus中使用. call是sql命令,任何工具都可以使用,call必须有括号,即例没有参数 call必须有括号,即例没有参数 idle> connect /as sysdba 已连接. sys@PO10> sys@PO10> create procedure p_test is 2 begin 3 n

  • ORACLE中查找定位表最后DML操作的时间小结

    在Oracle数据库中,如何查找,定位一张表最后一次的DML操作的时间呢? 方式有三种,不过都有一些局限性,下面简单的解析.总结一下. 1:使用ORA_ROWSCN伪列获取表最后的DML时间 ORA_ROWSCN伪列是Oracle 10g开始引入的,可以查询表中记录最后变更的SCN.然后通过SCN_TO_TIMESTAMP函数可以将SCN转换为时间戳,从而找到最后DML操作时SCN的对应时间.但是,默认情况下,每行记录的ORA_ROWSCN是基于Block的,除非在建表的时候开启行级跟踪. SE

  • Oracle call 和 exec的详解及区别

    Oracle 中 call 和 exec的区别 今天做项目使用Oracle,在做项目的过程中觉得很有意思,查找了一些资料,跟大家分享一下: 在sqlplus中: 在第三方提供的工具(如:plsqldev)  总结: exec是sqlplus的命令,只能在sqlplus中使用. call是sql命令,任何工具都可以使用,call必须有括号,即例没有参数 call必须有括号,即例没有参数 idle> connect /as sysdba 已连接. sys@PO10> sys@PO10> cr

  • ORACLE检查找出损坏索引(Corrupt Indexes)的方法详解

    索引 索引与表一样,也属于段(segment)的一种.里面存放了用户的数据,跟表一样需要占用磁盘空间.索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是一个独立于表的对象,可以存放在与表不同的表空间中.索引记录中存有索引关键字和指向表中数据的指针(地址).对索引进行的I/O操作比对表进行操作要少很多.索引一旦被建立就将被Oracle系统自动维护,查询语句中不用指定使用哪个索引. 从物理上说,索引通常可以分为:分区和非分区索引.常规B树索引.位图(bitmap)索引.翻

  • VMware下CentOS静默安装oracle12.2详细图文教程

    环境准备: VMware+CentOS,jdk 一.校验系统磁盘大小 1.命令 df -h 保证可用磁盘大小15GB(包括oracle安装时需要空间7.5GB + oracle安装zip包接近3G+安装包解压文件3G) 如果磁盘不满足,安装会失败,需要扩容! 二.安装准备 1.创建运行oracle数据库的系统用户和用户组 groupadd oinstall groupadd dba useradd -g oinstall -g dba -m oracle passwd oracle #不用管提示

  • 运行在容器中的Oracle XE-11g

    Oracle XE Oracle是这样介绍XE的:11g XE(Express Edition)简化版是在Oracle11gR2基础之上一个入门级的小体量数据库,免费用于开发/部署与发布,下载很快,使用简单. 特性 Oracle XE主要适用对象: 适用与适用Node.js, Python, PHP, Java, .NET, XML和开源项目的开发者 需要一个免费可用于DBA进行起步阶段的数据库培训或者部署 需要一个免费的起步阶段的数据库的独立软件提供商ISV(Independent Softw

  • Oracle数据库自动备份脚本分享(超实用)

    前言 众所周知数据是应用的核心部分,程序坏了换台机器重新发布就可以,但数据一旦丢失,造成的损失将不可挽回,程序发布到生产后,数据的备份便显得尤为重要,由于不一定所有的服务均有资金完成高级的备份如RAC和DG,在我们只有一台数据库服务器的,暂时采取最简单的备份策略,export出dmp进行保存. 一.备份脚本 1.初始化变量,记录开始日志 #变量 sysname=填写自己的系统名称 syspath=/home/oracle/databak/$sysname v_date=$(date '+%Y%m

  • Oracle基础:通过sqlplus执行sql语句后的结果进行判断

    这篇文章介绍一下如何对sqlplus执行的sql语句结果进行判断. 环境准备 使用Oracle的精简版创建docker方式的demo环境,详细可参看: https://www.jb51.net/article/153533.htm 常见问题 在sqlplus中执行sql语句,如果直接使用命令行的方式调用时会碰到两个问题: 问题1: 需要进行交互性的输入 问题2:结果的判断不能通过返回值来确认 解决方式 在脚本调用里,解决方式如下 问题1可以通过前文提到的Here Document来解决. 问题2

  • JDBC Oracle执行executeUpdate卡死问题的解决方案

    使用jdbc执行oracle的删除操作的时候程序卡死不动了. 问题分析: 对于这一类问题,一般都是数据库事务未提交,导致executeUpdate卡死. 所以解决方案: 1.在执行完executeUpdate 后,记得将事务提交con.commit(); 2.找到数据库客户端,执行commit操作. 如果以上操作还不行. 那么应该是数据库在执行 数据操作失败 or 事务未提交 之后 将需要执行的sql语句锁死了 Oracle的操作方式: 先查询锁定记录 : SELECT s.sid, s.ser

随机推荐