oracle 19c 统计信息详解

一、优化统计 (Optimizer Statistics )

优化统计收集了数据库及其对象的详细信息资料,查询优化器使用这些信息,为 SQL 命令选择最优的执行计划。

统计数据包括:

*数据表统计:数据行数、数据区块数、平均数据行长度

*列统计:列中的不同值数量、列中的 NULL 值数量、数据分布 (直方图) 、

扩展统计

*索引统计:叶块(leaf blocks)数量、分级数(Levels)、集群因子(Clustering

factor)

*系统统计:I/O 性能和利用率、CPU 性能和利用率

当参数 STATISTICS_LEVEL = TYPICAL (默认值) 或 ALL 时,Oracle 数据 库在自动任务 (AutoTask) 中默认启用优化统计采集,自动任务在计划调度的维 护窗口 (maintenance windows) 时段自动执行。 自动采集任务可用以下指令控

制:

启用 autotask 的自动优化采集,其中'auto optimizer stats collection' 是 视图 dba_autotask_client 中的预置名称

select client_name,status from dba_autotask_client ;

begin

dbms_auto_task_admin.enable(

client_name => 'auto optimizer stats collection',

operation => null,

window_name => null

) ;

end ;

/

-- 禁用 autotask 的自动优化采集

begin

dbms_auto_task_admin.disable(

client_name => 'auto optimizer stats collection',

operation => null,

window_name => null

) ;

end ;

/

二、手工采集统计

自动优化统计默认是在每天的维护窗口时段采集统计数据,如果在另外的时 段,表数据发生显著变化时,其统计信息将失效,这时将需要手工收集统计信息。 例如:

*不稳定的数据表:在一天内会被删除、或截断和重建

*发生大批量装载数据 (超过 10% 以上) 的对象

手 工 采 集 统 计 数 据 需 要 使 用 DBMS_STATS 程 序 包 中的 子 程 序 , 通 过 dbms_stats 包,可以查看和修改为数据库对象收集的优化器统计信息。Oracle RDBMS 允许收集多种不同类型的统计信息,以帮助提高性能。DBMS_STATS 这个包 只涉及优化器统计信息。Oracle 默认情况下会将此类自动统计信息收集设置为 打开状态,因此此包仅用于专门的手工收集的情况。可以使用 dbms_stats 并行 收集统计信息。
Gathering Optimizer Statistics

gather_database_stats

收集数据库中所有对象的统计信息:

estimate_percent

要估计的行百分比 (空表示计算) :有效范围为[0.000001,100]。

method_opt

FOR ALL [INDEXED | HIDDEN] COLUMNS [size_clause]

FOR COLUMNS [size clause] column [size_clause] [,column [size_clause]...]

size_clause is defined as size_clause := SIZE {integer | REPEAT | AUTO

| SKEWONLY}

- integer : 直方图存储桶数,范围为[1,2048]

- REPEAT : 只收集已经有直方图的列上的直方图。

- AUTO **:**根据数据分布和列的工作负载确定要在其上收集直方图的列。

- SKEWONLY : 根据列的数据分布确定要在其上收集直方图。

Degree

并行度,The default for degree is NULL。

Cascade

收集索引的统计数据。除了收集表和列统计信息外,使用此选项相当于对数据库 中的每个索引运行 GATHER_INDEX_STATS 过程。

no_invalidate

如果设置为 true,则不会使游标无效。如果设置为 false,该过程将立即使游标 失效。

示例:
execute dbms_stats.gather_database_stats(estimate_percent=>null) ; execute dbms_stats.gather_database_stats() ;
exec dbms_stats.gather_database_stats (degree=>4, cascade=>true) ; exec dbms_stats.gather_database_stats (no_invalidate=>true) ;
exec dbms_stats.gather_database_stats (method_opt => 'for all indexed') ; exec dbms_stats.gather_database_stats (method_opt=>'for all columns size auto',cascade=>true) ;
exec dbms_stats.gather_database_stats (method_opt =>'for all columns size 254') ;
exec dbms_stats.gather_database_stats (method_opt =>'for all columns size skewonly') ;
将 integer 即 bucket 的数据设置为 1,可以不使用直方图,如下所示:
exec dbms_stats.gather_database_stats (method_opt =>'for all columns size 1') ;

gather_dictionary_stats

收集 dictionary schemas 'SYS', 'SYSTEM'和 RDBMS 组件架构的统计信息。

示例:

execut dbms_stats.gather_dictionary_stats() ;

execut dbms_stats.gather_dictionary_stats(degree=>4, cascade=>TRUE) ;

gather_fixed_objects_stats

收集所有固定对象 (动态性能表) 的统计信息。

示例:

execut dbms_stats.gather_fixed_objects_stats() ;

execut dbms_stats.gather_fixed_objects_stats(no_invalidate=>true) ;

gather_index_stats

收集索引统计信息。

示例:

查询 scott 模式下的索引

select index_name,table_name from dba_indexes where owner='SCOTT' ;

为表 dept 的主键索引 PK_DEPT 进行统计数据

execute dbms_stats.gather_index_stats('SCOTT','PK_DEPT') ;

验证主键索引是否成功统计

select index_name,last_analyzed from dba_indexes where owner='SCOTT' ;

gather_schema_stats

收集模式中所有对象的统计信息。

示例:

为模式 scott 的所有表统计数据

execut dbms_stats.gather_schema_stats(ownname=>'scott') ;

验证模式 scott 的数据统计是否成功

select last_analyzed,table_name,owner,num_rows,sample_size from dba_tables where owner='SCOTT' ;

exec DBMS_STATS.GATHER_SCHEMA_STATS ('SH', degree=>4, cascade=>TRUE) ; execut dbms_stats.gather_schema_stats('sys') ;

gather_system_stats

收集系统统计信息。当 CBO 选择最佳查询路径时,需要使用数据库对象如表、 索引等的统计数据,以及操作系统的统计数据如 I/O 速度,CPU 周期等进行 SQL 的操作耗时计算,选择花费时间最少的执行计划为最佳执行计划。Oracle 使用 gather_system_stats 过程来统计操作系统数据。

Noworkload 将捕获 I/O 系统的特征。在此期间,Oracle 将估计 I/O 系统的 平均读取寻道时间和传输速度。此模式适用于所有工作负载。

示例:

execut ++++dbms++++ ++++_++++ ++++stats++++ .gather_system_stats(gathering_mode=>'NOWORKLOAD') ;

gather_table_stats

收集表和列 (和索引) 统计信息。

示例:

execute dbms_stats.gather_table_stats('scott','emp') ;

exec dbms_stats.gather_table_stats('sh', 'sales',method_opt=>'for all

columns size auto', cascade=>TRUE) ;

exec dbms_stats.gather_table_stats('sh', 'sales', method_opt=>'for all columns size skewonly') ;

exec dbms_stats.gather_table_stats('sh', 'sales',method_opt=>'for all columns size 254') ;

Deleting Statistics

delete_column_stats

删除与列相关的统计信息。

示例:

exec dbms_stats.delete_column_stats(ownname=>'scott',tabname=>'dept',colna me=>'deptno') ;

delete_database_stats

删除数据库中所有表的统计信息。

示例:

exec dbms_stats.delete_database_stats() ;

delete_dictionary_stats

删除所有字典架构的统计信息 ( "sys" 、"system"和 rdbms 组件架构) 。

示例:

exec dbms_stats.delete_dictionary_stats () ;

delete_fixed_objects_stats

删除所有固定表的统计信息。

示例:

exec dbms_stats.delete_fixed_objects_stats () ;

delete_index_stats

删除与索引相关的统计信息。

示例:

exec dbms_stats.delete_index_stats (ownname=>'scott',indname=>'pk_dept') ;

delete_schema_stats

删除整个模式的统计信息。

示例:

exec dbms_stats.delete_schema_stats(ownname=>'scott') ;

-- 删除 schema 统计

exec dbms_stats.delete_schema_stats('sh') ;

delete_table_stats

删除与表相关的统计信息。

示例:

exec dbms_stats.delete_table_stats (ownname=>'scott',tabname=>'dept') ; -- 删除 table 统计

exec dbms_stats.delete_table_stats('sh','sales') ;

实时统计信息

oracle@localhost \~\]$ sqlplus / as sysdba show pdbs conn / as sysdba alter session set container=PDB2; startup show con_name create user test identified by 123456; grant dba to test; conn test/[email protected]:1521/PDB2 create table testgather as select \* from dba_objects; set line 200 col table_name for a20 --如果没有收集统计信息,会是空的 select table_name,num_rows,blocks,notes from user_tab_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/f8a0c2b08432cb175cfbfc9ad294f272.webp) --如果没有收集统计信息,会是空的 col column_name for a20 col high_value for a20 col low_value for a20 col notes for a40 select column_name,high_value,low_value,notes from user_tab_col_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/725627b25b42e1aa4a1b078e8f694b25.webp) **收集表的统计信息** SQL\> exec dbms_stats.gather_table_stats('test','testgather',method_opt=\>'for all columns size 2'); 再执行一次查询,发现在 note 部分什么都没有。说明 real-time statistics 还没有收集。 --表级别 select table_name,num_rows,blocks,notes from user_tab_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/d249ee010e40395060c43e655dc3f21b.webp) --列级别 set line 200 col column_name for a20 col high_value for a20 col low_value for a20 col notes for a40 select column_name,high_value,low_value,notes from user_tab_col_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/5de8e33c58e5d4146a5f11b32b30d553.webp) 再次插入数据 insert into testgather select \* from testgather; commit; **--获取执行计划** 下图第二个红框中显示 load table conventional ,这表示在刚才插入数据的时候,数据库执 行了实时统计值收集的动作。 SQL \> select \* from table(dbms_xplan.display_cursor(format = \>'typical')); ![](https://file.jishuzhan.net/article/1711697466006441985/64bb6df077d3df416086413ecf2576a1.webp) 查看统计信息的表。 --表级别 select table_name,num_rows,blocks,notes from user_tab_statistics where table_name='TESTGATHER'; 列级别 set line 200 col column_name for a20 col high_value for a20 col low_value for a20 col notes for a40 select column_name,high_value,low_value,notes from user_tab_col_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/643fcefd5f2b3f93da023159246688dd.webp) 因为 19C 实时收集统计信息,其实只开发给 EXDATA 一体机使用,使用隐含参数来模拟。 这个参数是在 CDB 下生效,如果在 PDB 下改会报错,ORA-65040: operation not allowed from within a pluggable database conn / as sysdba alter session set container=CDB$ROOT; alter system set "_exadata_feature_on"=true scope=spfile; shutdown immediate startup alter pluggable database all open; conn test/[email protected]:1521/pdb1 set line 200 col column_name for a20 col high_value for a20 col low_value for a20 col notes for a40 select column_name,high_value,low_value,notes from user_tab_col_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/252d181d0f42cbc018232bde61c47a15.webp) 再次插入数据 insert into testgather select \* from testgather; commit; set line 200 col column_name for a20 col high_value for a20 col low_value for a20 col notes for a40 select column_name,high_value,low_value,notes from user_tab_col_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/97e35c439c68cfacedee84068dd44ada.webp) select table_name,num_rows,blocks,notes from user_tab_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/fcdfaa08bba2199540760a41e4ce623b.webp) 手动刷新进去 exec dbms_stats.flush_database_monitoring_info; select table_name,num_rows,blocks,notes from user_tab_statistics where table_name='TESTGATHER'; ![](https://file.jishuzhan.net/article/1711697466006441985/22b7b9ec0b68909c4c41cb9956a177b9.webp) set autotrace on; select count(\*) from testgather; 可以看到 289580=72395+217185,如果创建的表,刚开始没有数据的话。这里是准的。 ![](https://file.jishuzhan.net/article/1711697466006441985/fd02021393dd77779f4fa9771cdcbbf5.webp) 需要注意 1. 使用非 sys 用户 2. 这个特性只有 exdata 一体机

相关推荐
Lxinccode2 小时前
Java查询数据库表信息导出Word-获取数据库实现[1]:KingbaseES
java·数据库·word·获取数据库信息·获取kingbasees信息
豆沙沙包?3 小时前
5.学习笔记-SpringMVC(P61-P70)
数据库·笔记·学习
每次的天空4 小时前
Android学习总结之Room篇
android·学习·oracle
朴拙数科5 小时前
MongoDB Atlas与MongoDB连接MCP服务器的区别解析
服务器·数据库·mongodb
柏油5 小时前
MySQL InnoDB 行锁
数据库·后端·mysql
A-Kamen5 小时前
MySQL 存储引擎对比:InnoDB vs MyISAM vs Memory
数据库·mysql·spark
极限实验室5 小时前
【Workshop 第一期 - 北京站】搜索服务统一治理(跨引擎多个集群监控管理、流量管控、服务编排)
数据库
鹏翼丶6 小时前
搭建动态SQL取数
数据库·sql·动态sql
辰哥单片机设计6 小时前
PH传感器详解(STM32)
数据库·mongodb
JavaAlpha6 小时前
面试题:Redis 一次性获取大量Key的风险及优化方案
数据库·redis·bootstrap