暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

第5章. 统计数据

原创 由迪 2020-09-03
656

在查询转换器实现了对语句的逻辑优化以后,优化器就会根据语句选择可能的访问路径、关联方式及关联顺序,并由代价估算器针对不同方式进行代价估算(Cost Estimating),最终找出代价最低方式。这一优化过程也称为物理优化(Physical Optimization)。物理优化过程中,最重要的环节就是对可能的执行计划的代价估算,得出估算的代价值。最终,执行计划生成器根据估算的代价 选择代价值最下的执行计划。
在代价估算中,优化器根据系统处理能力、对象的大小以及需要读取的数据量等等信息估算出语句从相关对象上读取所需数据需要花费的代价。而这些信息主要来源于存储在系统中的统计数据
(Statistics)。
统计数据可以分为两个个层次:系统统计数据和对象统计数据。而这些统计数据的获取,则需要通过调用 Oracle 提供的包 DBMS_STATS 进行收集(对于对象的统计数据的收集,也可以通过命令
ANALYZE 来完成,但是它与 DBMS_STATS 存在少许差异,并且缺乏灵活性,如较难定制后台作业进行定期收集,因此我们推荐使用 DBMS_STATS)。下面我们分别介绍如何收集统计数据、已经
Oracle 如何计算相关的统计数据。
5.1 系统统计数据
系统处理能力是影响执行计划中操作代价的重要因素,DBMS_STATS 中有相应的存储过程
(GATHER_SYSTEM_STATS)来收集相关数据。这些系统统计数据(System Statistics)包括:CPU 转速、单数据块读的 IO 时间、多数据块读的 IO 时间,以及多数据块读的平均每次读取的数据块的数量等。相应的系统统计数据为:

• CPUSPEEDNW:CPU 在无负载模式下的处理速度,即每秒钟可以完成的机器指令数(或者说转数,Cycles),单位为百万次,10g 中默认值为 1,11g 中默认值为 100;
• CPUSPEED:CPU 负载模式下的处理速度,即每秒钟可以完成的机器指令数,单位为百万次;
• IOSEEKTIM:IO 寻址时间,即 IO 寻址需要的时间,单位为毫秒,默认值为 10;
• IOTFRSPEED:IO 传输速度,即每毫秒传输的字节数,默认值为 4096;
• MBRC:系统设置多数据块读的数据块数。
• SREADTIM:单数据块读的平均读取时间,单位为毫秒;
• MREADTIM:多数据块读的平均读取时间,单位为毫秒;
• MAXTHR:IO 系统的最大吞吐量,单位为每秒字节数;
• SLAVETHR:单个并行服务进程的最大吞吐量,单位为每秒字节数;

而对系统统计数据的收集,可以有两种模式进行:负载模式(WORKLOAD)和无负载模式
(NOWORKLOAD)。

• 无负载模式数据包括:CPUSPEEDNW、IOSEEKTIM 和 IOTFRSPEED;
• 载模式数据包括:CPUSPEED、MBRC、SREADTIM、MREADTIM、MAXTHR 和 SLAVETHR

其中无负载模式中相关统计数据在系统启动时被初始化,未被收集的数据则由无负载模式数据代入特定的公式(我们将在下一章节讨论相关代价估算公式)计算得出。而一旦负载模式的相关数 据被收集了,无负载模式中相关统计数据在做代价估算时就会被忽略。
5.1.1 系统统计数据收集
上节中我们提到,系统统计数据可以通过过程 DBMS_STATS.GATHER_SYSTEM_STATS 来收集,并且可以由参数控制是在负载模式还是在无负载模式下收集。

无负载模式
对于新上线的系统,或者负载情况相当不稳定的系统,可以采用无负载模式来收集系统统计数据。这种模式下,其它相关数据会由 Oracle 内部公式计算得出。不输入参数,或者输入参数gathering_mode => ‘NOWORKLOAD’,调用 DBMS_STATS.GATHER_SYSTEM_STATS 可以收集到无负载模式数据。

示例:
image.png
所有系统统计数据都被存储在系统数据字典 SYS.AUX_STATS$中。
image.png

负载模式
对于系统负载比较均匀、或者负载波动有规律的系统,推荐在负载模式下收集不同负载情况下的系统统计数据。负载模式数据收集有两种方式:手动启动和停止收集;自动收集。

•手动启动和停止收集的方法示例:
image.png
image.png

注意,只有在收集期间发生了单数据块读操作(索引扫描等),才能收集到 SREADTIM 数据; 只有在收集期间发生了多数据块读操作(全表扫描、快速完全索引扫描等),才能收集到 MBRC、MREADTIM 数据;只有在收集期间发生了并行操作,才能收集到 MAXTHR、SLAVETHR 数据。

image.png
以上数据中,DSTART 为收集开始时间;DSTOP 为收集结束时间。

• 自动收集的方法示例:
image.png
运行该过程后,即开始收集统计数据,在 interval(这里为 60)指定分钟数之后停止收集。
5.1.2 系统统计数据管理
收集到系统统计数据后,我们可以通过包 DBMS_STATS 中的多个存储过程对统计数据进行灵活管理。

收集副本
我们之前提到,系统收集到的系统统计数据会被存储在系统数据字典 AUX_STATS$中。并且, 优化器在进行代价估算时,也是由该数据字典读取到相关系统统计数据。而我们之前提供的收集方 法,就是将收集到的统计数据直接存入该数据字典中。除此以外,Oracle 还提供了其他方法,使我们收集到数据被存储在用户自己建的统计表中作为副本,而不直接存储到系统数据字典中。
要收集副本数据,我们首先要通过调用过程 CREATE_STAT_TABLE 来创建一个统计表。

输入参数:
• OWNNAME:统计表的所有者;
• STATTAB:统计表的名字;
• TBLSPACE:统计表所在的表空间,默认为 NULL,即存储在用户的默认表空间上;
• GLOBAL_TEMPORARY:是否为临时表,默认为非临时表;
image.png
创建好统计表后,我们就可以调用 DBMS_STATS.GATHER_SYSTEM_STATS 收集统计数据到统计表中。

输入参数:
• GATHERING_MODE:收集方式,接受数值:‘NOWORKLOAD’、‘START’、‘STOP’、
‘INTERVAL’,默认值为’NOWORKLOAD’;
• INTERVAL:负载模式下统计数据收集的间隔时间,当 GATHERING_MODE 指定为
'INTERVAL’时有效,默认值为 60;
• STATTAB:统计表的名字,默认为 NULL,如果为 NULL,统计数据被直接收集到系统数据字典中;
• STATID:统计数据副本的标识串,默认为 NULL;
• STATOWN:统计表的所有者,默认为 NULL,如果指定了 STATTAB 且 STATOWN 为
NULL,则为当前用户;

示例:
image.png
过程完成后,系统统计数据被存储到了表 DEMO.T_STATTAB 中。以下是该表中字段的描述(关于对象统计数据的具体含义,会在下节再做具体解释):

提示:统计表不仅可以用于存储系统统计数据的副本,还可以用于存储对象统计数据的副本。

• STATID VARCHAR2(30) 统计数据副本的标识串;
• TYPE CHAR(1) 统计数据类型:S:系统统计数据;T:表统计数据;I:索引统计数 据;C:字段统计数据;P:表的选项设置(11g 特性,下面章节会做具体介绍);
• VERSION NUMBER 版本号;
• FLAGS NUMBER 标志,对应于 AUX_STATS中的 FLAGS • C1 VARCHAR2(30) 当统计数据类型为 T、C或 P 时,数据为表名;当统计数据类型为 I 时,数据为索引名;当统计数据类型为 S 时,数据为状态,对应于 AUX_STATS中的 STATUS(COMPLETED, AUTOGATHERING, MANUALGATHERING, BADSTATS);
• C2 VARCHAR2(30) 当统计数据类型为 T、I 或C时,数据为分区名;当统计数据类型为 S 时,数据为系统数据收集开始时间,对应于 AUX_STATS中的 DSTART;当统计数据类型为 P 时,数据为选项名称; • C3 VARCHAR2(30) 当统计数据类型为 T、I 或C时,数据为子分区名;当统计数据类型为 S 时,数据为系统数据收集结束时间,对应于 AUX_STATS中的 DSTOP;当统计数据类型为 P 时,数据为选项数值(VARCHAR2 类型);
• C4 VARCHAR2(30) 当统计数据类型为 T 或 I 时,该字段无意义,数据为空;当统计数据类型为C时,数据为字段名;当统计数据类型为 S 时,数据为系统数据的类型:
CPU_SERIO 为 CPU 数据和串行 IO 的数据(SREADTIM、MREADTIM);PARIO 为并行 IO
的数据(MAXTHR、SLAVETHR);当统计数据类型为 P 时,该字段无意义,数据为空;
• C5 VARCHAR2(30) 当统计数据类型为 T、I、C或 P 时,数据为对象的所有者;当统计数据类型为 S 时,该字段无意义,数据为空;
• N1 NUMBER 当统计数据类型为 T 或C时,数据为记录行数(NUM_ROWS);当统计数据类型为 I 时,数据为被索引的记录数;当统计数据类型为 S 时,依据 C4,串

行 IO 的数据为 SREADTIM、并行 IO 的数据为 MAXTHR;当统计数据类型为 P 时,数据为选项数值(NUMBER 类型);
• N2 NUMBER 当统计数据类型为 T 时,数据为表的数据块数;当统计数据类型为C时,数据为字段密度(Density);当统计数据类型为 I 时,数据为索引的叶子数据块数;当统计数据类型为 S 时,依据 C4,串行 IO 的数据为 MREADTIM、并行 IO 的数据为 SLAVETHR;
• N3 NUMBER 当统计数据类型为 T 时,数据为表记录的平均长度;当统计数据类型为C时,该字段无意义,数据为空;当统计数据类型为 I 时,数据为索引的唯一键值数;当统计数据类型为 S 时,依据 C4,CPU_SERIO 数据为 CPUSPEED,PARIO 数据为
IOSEEKTIM;当统计数据类型为 P 时,该字段无意义,数据为空;
• N4 NUMBER 当统计数据类型为 T 或C时,数据为取样大小(Sample Size);当统计数据类型为 I 时,数据为平均每个键值所占用的叶子数据块数;当统计数据类型为
S 时,依据 C4,CPU_SERIO 数据为 CPUSPEED,PARIO 数据为 IOTFRSPEED;当统计数据类型为 P 时,该字段无意义,数据为空;
• N5 NUMBER 当统计数据类型为C时,数据为字段中的空值数;当统计数据类型为 I 时,数据为平均每个键值所指向的表数据块数;当统计数据类型为 T 或 S 时,依据
C4,CPU_SERIO 时无意义,数据为空,PARIO 数据为 CPUSPEEDNW;当统计数据类型为
P 时,该字段无意义,数据为空;
• N6 NUMBER 当统计数据类型为C时,数据为字段的最小值;当统计数据类型为
I 时,数据为索引的簇集因子(Clustering Factor);当统计数据类型为 T 或 S 时,该字段无意义,数据为空;当统计数据类型为 P 时,该字段无意义,数据为空;
• N7 NUMBER 当统计数据类型为C时,数据为字段的最大值;当统计数据类型为
I 时,数据为索引树的层数;当统计数据类型为 T 或 S 时,该字段无意义,数据为空; 当统计数据类型为 P 时,该字段无意义,数据为空;
• N8 NUMBER 当统计数据类型为C时,数据为字段的平均长度;当统计数据类型 为 I 时,数据为索引取样大小;当统计数据类型为 T 或 S 时,该字段无意义,数据为空; 当统计数据类型为 P 时,该字段无意义,数据为空;
• N9 NUMBER
• N10 NUMBER 当统计数据类型为C时,数据为字段柱状图(Histogram)结束点
的记录数;当统计数据类型为 I 时,数据为索引取样大小;当统计数据类型为 T、I 时, 数据为对象中被缓存在内存(Buffer Cache)的数据块数;当统计数据类型为 S 或 P 时, 该字段无意义,数据为空;
• N11 NUMBER 当统计数据类型为C时,数据为字段柱状图(Histogram)结束点的值;当统计数据类型为 I 时,数据为索引取样大小;当统计数据类型为 T 或 I 时,数据为对象数据块的缓存命中率;当统计数据类型为 S,且 C4 为 CPU_SERIO 时,数据为
MBRC;当统计数据类型为 P 时,该字段无意义,数据为空;
• N12 NUMBER 当统计数据类型为 T 或 I 时,数据为对象缓存相关统计数据的更新时间;当统计数据类型为C、S 或 P 时,该字段无意义,数据为空;
• D1 DATE 当统计数据类型为 T、I 或C时,数据为对象统计数据的最后分析时间;当统计数据类型为 S 时,该字段无意义,数据为空;当统计数据类型为 P 时,数据为选项最后更改时间;当统计数据类型为 P 时,该字段无意义,数据为空;
• R1 RAW(32)
• R2 RAW(32)
• CH1 VARCHAR2(1000)
删除系统统计数据(重新初始化)
调用过程 DBMS_STATS.DELETE_SYSTEM_STATS 可以删除统计表中的副本数据、或者重新初始化系统数据字典中的统计数据。

输入参数:
• STATTAB、STATID 和 STATOWN:参见之前解释; 示例:
image.png

提示:调用该过程,系统数据字典中的统计数据不会被真正删除,而是被重新初始化。如果要真正
删除系统数据字典中的数据,可以直接 DELETE 表 SYS.AUX_STATS$,但是不推荐这样做。

手工指定特定值
如果我们希望人为设定或修改某个系统统计数据,可以调用过程
DBMS_STATS.SET_SYSTEM_STATS。

输入参数:
• PNAME:需要设置的参数名称,可以是任意一个上面列出来的系统统计数据,如
CPUSPEEDNW。
• PVALUE:设置的新的数值。
• STATTAB、STATID 和 STATOWN:参见之前解释;
示例:
image.png
查询显示系统统计数据
系统统计数据存储在表 SYS.AUX_STATS$中,我们可以通过查询语句直接显示里面的数据。但是, 并非所有用户都能读取该表(我们也应该限制用户访问 SYS 用户下面的表)。可以通过调用过程
DBMS_STATS.GET_SYSTEM_STATS 来查询、显示特定统计数据。

输入参数:
• PNAME 、STATTAB、STATID 和 STATOWN:参见之前解释;

输出参数:
• STATUS:当前系统统计数据收集的状态:COMPLETED, AUTOGATHERING, MANUALGATHERING, BADSTATS;
• DSTART:当前系统统计数据收集的开始时间;
• DSOP:当前系统统计数据收集的结束时间;
• PVALUE:查询到的数值。
示例:
image.png
导出副本数据
副本数据除了可以从系统中收集外,还可以调用过程 DBMS_STATS.EXPORT_SYSTEM_STATS 直接将已有的存储在系统数据字典中的数据导出到统计表。

输入参数:
• STATTAB、STATID 和 STATOWN:参见之前解释; 示例:
image.png
导入副本数据
存储在统计表中的副本数据,可以由过程 DBMS_STATS.IMPORT_SYSTEM_STATS 导入到系统数据字典中,使之生效。

输入参数:
• STATTAB、STATID 和 STATOWN:参见之前解释; 示例:
image.png
导入数据是将统计表的覆盖已有的数据,而不会删除已有数据。导入副本数据之前,要确认副 本数据状态为 COMPLETED。
通过副本数据的导出、导入,我们可以实现兼容版本的不同数据库之间的系统统计数据的复制。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论