dbms_stats 导入导出表统计信息

简介:       在SQL tuning的过程中,不正确的或者过时的统计信息导致使用不正确的执行计划被采用的情况比比皆是。 当然对于这个情形,我们可以通过收集最新的统计信息来达到优化的目的。

      在SQL tuning的过程中,不正确的或者过时的统计信息导致使用不正确的执行计划被采用的情况比比皆是。 当然对于这个情形,我们可以通过收集最新的统计信息来达到优化的目的。而且Oracle之前的统计信息会自动保留。除此之外,我们也可以通过备份的方式来实现导入导出统计信息。本文即使描述的即是该方式,同时并对比了不同统计信息的执行计划,最后给出了一个批量导出统计信息的代码。
      有关导入导出统计信息的具体步骤及使用情形可参考:
           dbms_stats 导入导出 schema 级别统计信息

 

1、创建演示环境

scott@USBO> select * from v$version where rownum<2;   
   
BANNER   
--------------------------------------------------------------------------------    
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production   

--创建演示表,并插入所有sys用户的表记录
scott@USBO> create table t1 nologging tablespace tbs1 as select * from dba_objects where owner='SYS' and object_type='TABLE';

--添加所有非sys的记录
scott@USBO> insert into t1 select * from dba_objects where owner <>'SYS';

43172 rows created.

scott@USBO> commit;
scott@USBO> create index i_t1_owner on t1(owner);      --->添加索引            

--收集统计信息
scott@USBO> exec dbms_stats.gather_table_stats('SCOTT','T1',cascade=>true);

PL/SQL procedure successfully completed.

--此时表上sys用户的表位1001个
scott@USBO> select owner,count(*) from t1 where owner='SYS' group by owner;

OWNER                            COUNT(*)
------------------------------ ----------
SYS                                  1001

--下面是其执行计划
scott@USBO> set autot trace exp;
scott@USBO> select owner,count(*) from t1 where owner='SYS' group by owner;

Execution Plan
----------------------------------------------------------
Plan hash value: 832695366

-----------------------------------------------------------------------------------
| Id  | Operation            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |            |     1 |     8 |     4   (0)| 00:00:01 |
|   1 |  SORT GROUP BY NOSORT|            |     1 |     8 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN   | I_T1_OWNER |  1425 | 11400 |     4   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

scott@USBO>set autot off;

2、导出统计信息

--首先创建用于存放统计信息的舞台表
scott@USBO> exec dbms_stats.create_stat_table (ownname => 'SCOTT', stattab => 'ST_T1', tblspace => 'TBS1');

PL/SQL procedure successfully completed.

--下面使用export_table_stats过程导出统计信息,此时statid为A
scott@USBO> exec dbms_stats.export_table_stats(ownname =>'SCOTT',tabname=>'T1',stattab=>'ST_T1',statid => 'A');

PL/SQL procedure successfully completed.

--插入新的记录,此时为SYS非表类型的所有对象,有30043条
scott@USBO> insert into t1 nologging select * from dba_objects where owner='SYS' and object_type<>'TABLE';

30043 rows created.

scott@USBO> commit;

--收集统计信息
scott@USBO> exec dbms_stats.gather_table_stats('SCOTT','T1',cascade=>true);

--再次导出统计信息,注意,此时的statid为B
scott@USBO> exec dbms_stats.export_table_stats(ownname =>'SCOTT',tabname=>'T1',stattab=>'ST_T1',statid => 'B');

PL/SQL procedure successfully completed.

--下面我们分析原SQL的执行计划
scott@USBO> set autot trace exp;
scott@USBO> select owner,count(*) from t1 where owner='SYS' group by owner;

Execution Plan
----------------------------------------------------------
Plan hash value: 453826725

------------------------------------------------------------------------------------
| Id  | Operation             | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |     1 |     6 |    58   (0)| 00:00:01 |
|   1 |  SORT GROUP BY NOSORT |            |     1 |     6 |    58   (0)| 00:00:01 |
|*  2 |   INDEX FAST FULL SCAN| I_T1_OWNER | 31349 |   183K|    58   (0)| 00:00:01 |
------------------------------------------------------------------------------------

--上面的执行计划中使用了最新的统计信息,而且预估的行数31349接近于表上的行数

3、导入过旧的统计信息并对比执行计划

--下面使用import_table_stats导入之前过旧的统计信息
scott@USBO> exec dbms_stats.import_table_stats(ownname => 'SCOTT', tabname => 'T1', stattab => 'ST_T1', -
> statid => 'A', no_invalidate => true);

PL/SQL procedure successfully completed.

--再次查看原SQL的执行计划
scott@USBO> select owner,count(*) from t1 where owner='SYS' group by owner;

Execution Plan
----------------------------------------------------------
Plan hash value: 832695366

-----------------------------------------------------------------------------------
| Id  | Operation            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |            |     1 |     8 |     4   (0)| 00:00:01 |
|   1 |  SORT GROUP BY NOSORT|            |     1 |     8 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN   | I_T1_OWNER |  1425 | 11400 |     4   (0)| 00:00:01 |
-----------------------------------------------------------------------------------
--Author : Leshami   Blog : http://blog.csdn.net/leshami
--从上面的执行计划中来看,尽管执行计划与先前的两个执行计划相同,但预估的行数是之前的行数,只有1425条记录
--也即是由于过时的统计信息造成的

4、批量导出表统计信息

--下面的匿名pl/sql块可以批量导出统计信息,可以用于SQL语句涉及到多表的情形,可以把相关的表统计信息全部导出
--需要注意的是表的名字不要超过28,因为我这里定义的统计信息备份表以"S_"开头占据了2个字符
--可以根据自己的情形修改其代码,如添加表空间参数等。
--对于披量导入表统计信息的脚本,大家可以参照下面的脚本修改,使用过程import_table_stats
DECLARE
   v_table_name   VARCHAR2 (30);
   v_stat_name    VARCHAR2 (35);
   v_sql_stat     VARCHAR2 (200);
   v_schema       VARCHAR2 (30) := 'SCOTT';

   --Define your table you want to export stat
   CURSOR cur_tab
   IS
      SELECT table_name
        FROM dba_tables
       WHERE table_name IN ('EMP', 'DEPT', 'BONUS');
BEGIN
   FOR cur_rec IN cur_tab
   LOOP
      v_stat_name := 'S_' || cur_rec.table_name;

      v_sql_stat := 'BEGIN DBMS_STATS.create_stat_table (''' || v_schema || ''' , ''' || v_stat_name || '''); END;';

      --            DBMS_OUTPUT.put_line (v_sql_stat);
      EXECUTE IMMEDIATE v_sql_stat;

      v_sql_stat := 'BEGIN DBMS_STATS.export_table_stats(''' || v_schema || ''',tabname=>''' || cur_rec.table_name || ''',stattab=>''' || v_stat_name || '''); END;';

      --        DBMS_OUTPUT.put_line (v_sql_stat);
      EXECUTE IMMEDIATE v_sql_stat;
   END LOOP;
END;


Oracle&nbsp;牛鹏社    Oracle DBsupport

更多参考

DML Error Logging 特性 

PL/SQL --> 游标

PL/SQL --> 隐式游标(SQL%FOUND)

批量SQL之 FORALL 语句

批量SQL之 BULK COLLECT 子句

PL/SQL 集合的初始化与赋值

PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录

SQL tuning 步骤

高效SQL语句必杀技

父游标、子游标及共享游标

绑定变量及其优缺点

dbms_xplan之display_cursor函数的使用

dbms_xplan之display函数的使用

执行计划中各字段各模块描述

使用 EXPLAIN PLAN 获取SQL语句执行计划

目录
相关文章
|
缓存 数据安全/隐私保护 Sentinel
断路精灵:探秘Sentinel熔断策略的神奇效果
断路精灵:探秘Sentinel熔断策略的神奇效果
220 0
|
弹性计算 Linux 云计算
阿里云上更新幻兽帕鲁Palworld服务器详细教程,附幻兽帕鲁搭建教程
如何快速在阿里云上更新幻兽帕鲁服务器?幻兽帕鲁更新之后,服务器需要同步更新才能继续游戏,大家可以按照以下操作完成服务升级。阿里云上更新幻兽帕鲁Palworld服务器详细教程,附幻兽帕鲁搭建教程。
|
5月前
|
传感器 自然语言处理 监控
快速部署实现Bolt.diy
Bolt.diy 是 Bolt.new 的开源版本,提供灵活的自然语言交互与全栈开发支持。基于阿里云函数计算 FC 和百炼模型服务,最快5分钟完成部署。新手注册阿里云账号后可领取免费额度,按指引开通相关服务并授权。通过项目模板一键部署,配置 API-KEY 后即可使用。Bolt.diy 支持多种场景,如物联网原型开发、久坐提醒、语音控制灯光等,助力快速实现创意应用。
2385 22
|
Shell Android开发 C++
利用Wrap Shell Script定位Android Native内存泄漏
## 前提条件 - Android版本为8.0以上 ## 环境配置 - cd到/src/main目录下,新建shell目录,同时shell目录下配置与libs目录下相同平台的目录,如下app下的层级结构,可看到shell/lib下具有与libs下相同的平台目录结构 ```c ── AndroidManifest.xml ├── java ├── libs │   ├── a
3839 0
|
SQL 安全 关系型数据库
Kingbase(人大金仓数据库)(总结全网精华,虚拟机:从安装到操作数据库一条龙)
KingbaseES 是一款由中国人大金仓信息技术股份有限公司自主研发的通用关系型数据库管理系统(RDBMS),专为中国市场设计,广泛应用于政府、金融、能源、电信等多个关键行业。它是国产数据库的代表之一,以其高安全性、高可用性和高性能著称,符合中国信息技术领域的自主可控要求。以下是关于KingbaseES的一些关键特点和功能:
2132 0
|
安全 搜索推荐 数据库
网站被黑检测与网站被黑处理方法
看到此文后,我认为你应该试着通过此文的方法检测一下你的网站是否被黑,因为有可能你的网站被黑了,连你自己都不知道,从下面的图片可以明显的看得出,我的网站也曾被黑过,但这位大神并没有打算处理我的网站,所以只是在网站上传一个文件来提醒我的,或许大家的网站中也有类似的情况。
11301 0
|
网络协议 Ubuntu 安全
Linux常用命令速查册,再也不用费脑细胞了
Linux常用命令速查册,再也不用费脑细胞了
Linux常用命令速查册,再也不用费脑细胞了
|
弹性计算 固态存储 数据可视化
阿里云服务器报价费用一年价格表(2022更新)
2022阿里云服务器租用费用及优惠活动价格表CPU内存带宽系统盘价格详单
3037 0
阿里云服务器报价费用一年价格表(2022更新)
|
存储 缓存 异构计算
ZYNQ裸板:BRAM篇
在 ZYNQ SOC 开发过程中, PL 和 PS 之间经常需要做数据交互。对于传输速度要求较高、数据量大、地址连续的场合,可以通过 AXI DMA 来完成。而对于数据量较少、地址不连续、长度不规则的情况,此时 AXIDMA 便不再适用了。针对这种情况,可以通过 BRAM 来进行数据的交互。
1181 0
|
弹性计算 应用服务中间件
阿里云服务器备案服务码申请图文教程以及常见问答解答
一台阿里云服务器最多可以申请5个备案服务码,备案服务码在备案时可用于验证,阿小云来详细说下阿里云服务器备案服务码申请流程
3632 0
阿里云服务器备案服务码申请图文教程以及常见问答解答