【Oracle专栏】更新多个表的统计信息

Oracle && OceanBase 相关文档,希望互相学习,共同进步

风123456789~-CSDN博客


1.背景

今天执行truncate部分表后,发现user_tables 的num_rows 还是原来的数据,于是进行手动更新。在Oracle中,统计信息对于优化器的决策至关重要。优化器使用统计信息来确定执行查询的最佳路径。

当表中的数据发生大量变化时,优化器可能无法做出最佳决策,因为它依赖的统计信息可能已经过时。统计信息未及时更新 会导致oracle 基于成本的执行计划可能不是最优,查看执行计划是没问题的,但sql实际执行起来确很慢。其中,DBMS_STATS包中的GATHER_TABLE_STATS过程是一种用于收集表、列和索引统计信息的强大工具。通过定期运行DBMS_STATS.GATHER_TABLE_STATS过程,可以确保优化器具有最新的统计信息,从而做出更好的决策。

本文针对oracle数据库的统计信息的手动更新相关内容进行整理、实验。

2. 实验

2.1 实验- 更新指定schema 统计信息

sql 复制代码
--一次性收集某个模式(Schema)下所有表的统计信息,不用逐表操作
EXEC DBMS_STATS.GATHER_SCHEMA_STATS('模式名');

或者

--更精细化统计
BEGIN
  DBMS_STATS.GATHER_SCHEMA_STATS(
    ownname          => '模式名',
    estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,  -- 自动决定采样比例
    method_opt       => 'FOR ALL COLUMNS SIZE AUTO',  -- 自动决定是否建直方图
    degree           => 4,                            -- 并行度,加快速度
    cascade          => TRUE                          -- 同时收集索引统计信息
  );
END;
/

参数说明:

‌ ownname‌:模式名,也就是表的所有者。

‌ estimate_percent‌:采样比例。用 DBMS_STATS.AUTO_SAMPLE_SIZE 让 Oracle 自己决定,通常推荐;也可以手动指定如 100 表示全量分析。

‌ method_opt‌:控制直方图收集方式。'FOR ALL COLUMNS SIZE AUTO' 是常用配置,让 Oracle 根据数据分布自动决定。

‌ degree‌:并行度。表多或大时设置并行(如 4、8)明显加快速度,但要考虑系统负载。

‌cascade‌:设为 TRUE 时,会连同索引统计信息一起收集,建议开启

例子:

sql 复制代码
BEGIN
  DBMS_STATS.GATHER_SCHEMA_STATS('FENG');
END;

2.2 实验 -更新指定表的统计信息

1)知识点

sql 复制代码
DBMS_STATS.GATHER_TABLE_STATS函数的语法如下:

DBMS_STATS.GATHER_TABLE_STATS (
  ownname VARCHAR2,
  tabname VARCHAR2,
  partname VARCHAR2,
  estimate_percent NUMBER,
  block_sample BOOLEAN,
  method_opt VARCHAR2,
  degree NUMBER,
  granularity VARCHAR2,
  cascade BOOLEAN,
  stattab VARCHAR2,
  statid VARCHAR2,
  statown VARCHAR2,
  no_invalidate BOOLEAN
);

ownname:指定表所在的模式名。如果为NULL,则默认为当前模式。

tabname:指定要收集统计信息的表名。

partname:指定要收集统计信息的分区名。如果为NULL,则收集整个表的统计信息。

estimate_percent:指定要收集的样本百分比。

如果为NULL,则默认为100,即收集整个表的统计信息。

block_sample:指定是否使用块采样来收集统计信息。

如果为TRUE,则使用块采样;如果为FALSE,则使用完全采样。默认为FALSE。

method_opt:指定收集统计信息的方法选项。

包括'FOR ALL COLUMNS SIZE AUTO'、'FOR COLUMNS column_list SIZE AUTO'等选项,用于指定要收集统计信息的列和如何收集。

degree:指定并行度,即用于收集统计信息的并行进程数。

如果为NULL,则使用数据库的默认并行度。

granularity:指定收集统计信息的粒度。可设为AUTO'、'ALL'、'COLUMNS'、'INDEXES'等

如,'AUTO'表示自动选择粒度;'ALL'表示收集所有级别的统计信息。

cascade:指定是否级联收集相关对象的统计信息,如索引、触发器等。

如果为TRUE,则级联收集;如果为FALSE,则只收集指定表的统计信息。

stattab:指定存储统计信息的表名。如果为NULL,则使用默认的统计信息表。

statid:指定统计信息的ID。如果为NULL,则Oracle会自动生成一个唯一的ID。

statown:指定存储统计信息的模式名。如果为NULL,则使用当前模式。

no_invalidate:指定是否使现有的统计信息无效。

如果设置为TRUE,则保留现有的统计信息,并在收集新统计信息后将其标记为无效。如果为FALSE或NULL,则在收集新统计信息后删除现有的统计信息。

sql 复制代码
--更新指定表的统计信息
BEGIN
    DBMS_STATS.GATHER_TABLE_STATS(
              ownname => USER,
              tabname => 'SUN_PUBLIC_INFO',
              cascade => TRUE
            );
END;
/

执行截图: 6百万数据,大约执行5分钟

sql 复制代码
或者:
call dbms_stats.gather_table_stats(user,'XPT_BANK_FENG');
call dbms_stats.gather_table_stats('FENG','TEM_TABLE');


SELECT TABLE_NAME, LAST_ANALYZED,a.* 
FROM ALL_TAB_STATISTICS a WHERE A.OWNER = 'FENG';

执行后,查询截图:

2.3 实验 -更新 多个表的统计信息

sql 复制代码
--编写函数,循环更新
create or replace function get_num_rows(p_tname varchar2) RETURN VARCHAR2 IS
    vResult  varchar2(2);
    vFunctionName varchar2(1000);
    vTableName    varchar2(500);
    vMsg          varchar2(1000);
    vCount        number;
    pDataIssue    varchar2(7);
  begin
    vResult       := '0';
    pDataIssue    := to_char(sysdate,'yyyy-mm');
    vTableName    := '' ;   --'OPEN_CNT_ASSCON';

    vFunctionName := 'get_num_rows -更新';
    begin
        GET_LOGGER(pDataIssue, 'get_num_rows', vTableName, '0', '开始跑批');

        FOR t IN (SELECT table_name FROM user_tables t
                  WHERE t.table_name  like 'SUN_PUBLIC_%'or t.table_name like '%RPT%'
                  ) 
        LOOP
            DBMS_STATS.GATHER_TABLE_STATS(
              ownname => USER,
              tabname => t.table_name,
              cascade => TRUE
            );
            GET_LOGGER(pDataIssue, 'get_num_rows', t.table_name, '0', '结束');
       END LOOP;
       GET_LOGGER(pDataIssue, 'get_num_rows', '', '0', '结束跑批');

    EXCEPTION
      WHEN OTHERS THEN
        vMsg := '报错位置:' || dbms_utility.format_error_backtrace || '报错信息:' ||
                substr(SQLERRM, 1, 200);
        GET_LOGGER(pDataIssue, vFunctionName, vTableName, '3', vMsg);
        vResult := '1';
    END;
    return vResult;
end;

查询更新后的统计信息:

sql 复制代码
select T.table_name,T.num_rows from user_tables t
where t.table_name  like 'SUN_PUBLIC_%'
or t.table_name like '%RPT%'
ORDER BY 1

2.4 查看 数据表上次统计更新的时间

sql 复制代码
--查看上次统计信息更新的时间
SELECT TABLE_NAME, LAST_ANALYZED,a.* 
FROM ALL_TAB_STATISTICS a WHERE A.OWNER = 'FENG';

2.5 自动化脚本更新

sql 复制代码
--将如下两个脚本存放到同一目录下,注意修改数据库配置参数,然后使用windows计划任务定期执行动态更新;
--​来源 https://blog.51cto.com/u_14286115/3327958,未验证,应该是可以的。

​
脚本1:自动更新Oracle统计信息.bat
title 自动更新Oracle统计信息[%date%%time%]
sqlplus userName/passWord@192.168.0.1/db_name @gen_sqls.sql | find "call dbms_stats.gather_table_stats">stats_sqls.sql
echo exit>>stats_sqls.sql
sqlplus userName/passWord@192.168.0.1/db_name @stats_sqls.sql
echo 脚本执行完成

 

脚本2:gen_sqls.sql
select
'call dbms_stats.gather_table_stats(''用户名'','''|| TABLE_NAME ||''');' as sqls
from user_tables a
where a.last_analyzed <sysdate-7
and num_rows > 1000
order by num_rows ;
exit;

3.总结

在Oracle数据库CBO基于成本的优化器体系当中,统计信息是优化器生成合理执行计划的核心输入源。统计信息失真、缺失、过期是线上SQL性能抖动、执行计划漂移最主要诱因之一。大量生产故障根因均来自统计信息维护不当:大表批量DML之后统计信息未刷新、直方图丢失、自动收集任务窗口不合理、参考数据表统计信息被自动任务覆盖等。

在Oracle数据库中,DBMS_STATS是一个强大的包,它提供了多种用于收集数据库对象统计信息的函数。其中,DBMS_STATS.GATHER_TABLE_STATS函数是最常用的一种,用于收集表、列和索引的统计信息。这些信息对Oracle的优化器非常重要,它可以帮助优化器制定更有效的查询计划。通过收集统计信息,Oracle可以更好地理解数据的分布和特征,从而更准确地评估查询的成本和效率。

  • 只更新单模式:DBMS_STATS.GATHER_SCHEMA_STATS
  • 只更新单表:DBMS_STATS.GATHER_TABLE_STATS
  • 更新整个数据库:DBMS_STATS.GATHER_DATABASE_STATS

应用场景:

  1. 数据库迁移:在将数据库从一个环境迁移到另一个环境时,需要收集源数据库的统计信息,并在目标数据库中重新收集统计信息,以确保优化器能够制定正确的查询计划。

  2. 数据表修改:当数据表的结构或数据发生重大变化时(如添加新列、删除列、大量数据插入或删除等),需重新收集统计信息,确保优化器能够准确评估查询的成本和效率。

  3. 定期维护:为了保持数据库性能的稳定和高效,需要定期收集统计信息。可以通过设置自动化任务或使用Oracle提供的自动收集统计信息的特性来实现

实验验证:ok


项目管理--相关知识

项目管理-项目绩效域1/2-CSDN博客

项目管理-项目绩效域1/2_八大绩效域和十大管理有什么联系-CSDN博客

项目管理-项目绩效域2/2_绩效域 团不策划-CSDN博客

高项-案例分析万能答案(作业分享)-CSDN博客

项目管理-计算题公式【复习】_项目管理进度计算题公式:乐观-CSDN博客

项目管理-配置管理与变更-CSDN博客

项目管理-项目管理科学基础-CSDN博客

项目管理-高级项目管理-CSDN博客

项目管理-相关知识(组织通用治理、组织通用管理、法律法规与标准规范)-CSDN博客


Oracle其他文档,希望互相学习,共同进步

Oracle-找回误删的表数据(LogMiner 挖掘日志)_oracle日志挖掘恢复数据-CSDN博客

oracle 跟踪文件--审计日志_oracle审计日志-CSDN博客

ORA-12899报错,遇到数据表某字段长度奇怪现象:"Oracle字符型,长度50"但length查却没有50_varchar(50) oracle 超出截断-CSDN博客

EXP-00091: Exporting questionable statistics.解决方案-CSDN博客

Oracle 更换监听端口-CSDN博客

相关推荐
实心儿儿4 小时前
MySQL — 库的操作
数据库·mysql·oracle
隔窗听雨眠5 小时前
Oracle普通表自动改造分区表:从评估到自动化维护的完整实战指南
oracle
我要见SA姐116 小时前
告别 Copilot?Codex 本地化部署指南
运维·数据库·机器学习·oracle·回归
我要见SA姐118 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
数据库·ide·vscode·oracle·编辑器
这个DBA有点耶19 小时前
异构数据集成怎么做?5 种同步方案对比 + 金融级 CDC 实战解析
数据库·oracle·架构
oradh1 天前
Oracle联机日志文件损坏故障总结
数据库·oracle·oracle联机日志文件损坏
辰辉创聚1 天前
炎症与免疫相关细胞因子:信号通路、分类及科研检测应用
python·oracle·nycodenz·重组il-6蛋白·抗tnf-α抗体·il-1β蛋白
风123456789~1 天前
【Oracle专栏】明明有索引,但报ORA-08102未找到索引
oracle
Leon-Ning Liu2 天前
Oracle 19c ASMB 进程 PGA 内存泄漏排查实战 (Bug 38610635)
数据库·oracle