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/123456@192.168.1.10: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';

--如果没有收集统计信息,会是空的

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';

收集表的统计信息

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';

--列级别

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';

再次插入数据

insert into testgather select * from testgather;

commit;

--获取执行计划

下图第二个红框中显示 load table conventional ,这表示在刚才插入数据的时候,数据库执 行了实时统计值收集的动作。

SQL > select * from table(dbms_xplan.display_cursor(format = >'typical'));

查看统计信息的表。

--表级别
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';

因为 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/123456@192.168.1.10: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';

再次插入数据

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';

select table_name,num_rows,blocks,notes from user_tab_statistics where table_name='TESTGATHER';

手动刷新进去

exec dbms_stats.flush_database_monitoring_info;

select table_name,num_rows,blocks,notes from user_tab_statistics where

table_name='TESTGATHER';

set autotrace on;

select count(*) from testgather;

可以看到 289580=72395+217185,如果创建的表,刚开始没有数据的话。这里是准的。

需要注意

  1. 使用非 sys 用户

  2. 这个特性只有 exdata 一体机

相关推荐
计算机学长felix1 分钟前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
小码的头发丝、1 小时前
Django中ListView 和 DetailView类的区别
数据库·python·django
Karoku0661 小时前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
周全全2 小时前
MySQL报错解决:The user specified as a definer (‘root‘@‘%‘) does not exist
android·数据库·mysql
白云如幻2 小时前
MySQL的分组函数
数据库·mysql
荒川之神2 小时前
ORACLE 闪回技术简介
数据库·oracle
时差9533 小时前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database
让学习成为一种生活方式3 小时前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
Mephisto.java3 小时前
【大数据学习 | kafka高级部分】kafka的优化参数整理
大数据·sql·oracle·kafka·json·database
秋意钟4 小时前
MySQL日期类型选择建议
数据库·mysql