Oracle数据库11g新特性:其他特性
2008-12-16 13:01:40 来源:WEB开发网新进程
每个新版本的 Oracle 数据库中都会引入一组新进程的新缩写。下面是 Oracle 数据库 11g 第 1 版中的新缩写列表:
进程 | 名称 | 描述 |
ACMS | 内存服务器原子控制文件 | 仅适用于 RAC 实例中。执行分布式 SGA 更新时,ACMS 可确保在所有实例上发生更新。如果某个实例上的更新失败,此进程也会在所有实例上回滚更新。可将 ACMS 视为两阶段提交协调器进程,用于 RAC 集群中的 SGA 更新。 |
DBRM | 数据库资源管理器 | 执行资源规划和其他与资源管理器相关的任务 |
DIA0 | 诊断进程 0 | 检测挂起情况和死锁。将来可能会引入多个进程,因此将名称设置为 diag0。将来如果引入其他进程,将分别命名为 dia1、dia2 等。 |
DIAG | 诊断进程 | 执行诊断、转储跟踪文件(如有必要)以及执行全局 oradebug 命令 |
FBDA | 闪回数据存档器 | Oracle 数据库 11g 提供新的“闪回存档”,用于写入对表所作的更改(请参阅本系列的“事务管理”部分)。此进程将写入闪回存档。 |
GTX0 | 全局事务进程 0 | 在 RAC 集群中,Oracle 数据库现在提供改进的 XA 事务处理。此进程协调 XA 事务。如果 XA 上的数据库负载增长,将自动创建更多进程,分别命名为 GTX1、GTX2,直至 GTXJ。 |
KATE | ASM 临时任务处理器 | 毫无疑问,这是所有新进程中最长的名称。它是在 ASM 实例上出现的,而不出现在数据库上。(有关新特性“快速磁盘重新同步”的信息,请参阅本系列中有关 ASM 的部分。)当磁盘脱机时,此进程将代替磁盘对 ASM 元文件执行代理 I/O。 |
MARK | 为重新同步协调器标记分配单元 | 有关 ASM 磁盘组弹性的更多详细信息,请参阅 ASM 部分。当磁盘出现故障时将会脱机,从而导致写入内容丢失。在这种情况下,此进程会将 ASM 分配单元 (AU) 标记为陈旧。当磁盘联机时,陈旧的段将被刷新。 |
SMCO | 空间管理器 | SMCO 是主空间管理进程,可动态分配和回收空间。它将生成从进程 Wnnn 以执行这些任务。 |
VKTM | 虚拟计时器进程 | 提供时钟时间(每秒钟更新一次)。以提升的权限运行时,此进程每 20 毫秒更新一次。 |
W000 | 空间管理工作器进程 | 执行从 SMCO 收到的指令。根据需要生成更多进程,命名为 W000、W001 等。 |
着色的 SQL
此新特性不会将 SQL 语句涂上颜色,而是类似于将其标记为“重要”。
假设您正在对某个性能问题进行故障诊断,您怀疑该问题是由某条 SQL 语句导致的。您希望在每个自动负载信息库 (AWR) 快照中捕获该 SQL 语句。但 AWR 快照并不捕获所有 SQL 语句,而只捕获前几条语句。如何强制快照捕获特定的 SQL,而不管它是否包括在前几条 SQL 语句?
程序包 dbms_workload_repository 中的 add_colored_sql() 过程将 SQL 标记为“着色的”,或者将其标记为重要,应该在每个 AWR 快照中捕获该 SQL,而不管它是否包括在前几条 SQL 语句中。首先确定 SQL 语句,然后获取其 SQL_ID.要对该语句着色,请使用以下命令:
begin
dbms_workload_repository.add_colored_sql(
sql_id => 'ff15115dvgukr'
);
end;
要找出已着色的 SQL,可以查询 AWR 表 WRM$_COLORED_SQL:
SQL> SELECT * FROM wrm$_colored_sql;
DBID SQL_ID OWNER CREATE_TI
---------- ------------- ---------- ---------
2965581158 ff15115dvgukr 1 05-APR-08
之后,将在每个快照中捕获 ID 为 ff15115dvgukr 的 SQL 语句,即使该语句不包括在前几条 SQL 语句中。(当然,该 SQL 必须位于库缓存中才能在 AWR 快照中捕获它。)
但是,如果 SQL 不再需要着色(即,该语句不再重要,没有必要捕获它)时怎么办呢?可以通过反向执行该过程来取消着色。
begin
dbms_workload_repository.remove_colored_sql(
sql_id => 'ff15115dvgukr'
);
end;
当您要在优化练习中关注某个 SQL 时,此特性极为有用。
OLTP 表压缩
长期以来,压缩一直作为 Oracle 数据库特性以这样或那样的形式存在着。
压缩始终是非常占用 CPU 的过程,并且需要花费一定时间。通常,如果压缩数据,则数据必须解压缩后才能使用。虽然此要求在数据仓库环境(SQL 通常在大量的行上运行,漫长的响应时间通常是可以容忍的)中是可以接受的,但在 OLTP 环境中可能无法接受。
现在,在 Oracle 数据库 11g 中,可以执行以下命令:
create table my_compressed_table (
col1 number(20),
col2 varchar2(300),
...
)
compress for all operations
“compress for all operations”子句在所有 DML 活动(如 INSERT、UPDATE 等)上执行压缩。压缩在所有 DML 活动上发生,而不像前几个版本那样,只在直接路径插入上发生。
这会降低 DML 的速度吗?不一定。这正是该新特性的最大优点。向表中插入行时不会发生压缩。相反,在插入行时,这些行将被解压缩,然后以常规方式插入。当以解压缩方式插入(或更新)一定数量的行时,将执行压缩算法并压缩块中所有解压缩的行。换句话说,将压缩块,而不是行。在 RDBMS 代码内部定义压缩发生的阈值。
压缩机制
请看一个 ACCOUNTS 表,它包含以下记录:
在数据库内部,假定一个数据库块包含上述所有行。
解压缩的块看上去是这样的:记录中的所有字段(列)都包含数据。压缩此块时,数据库首先计算在所有行中发现的重复值,将这些值移出行外,然后将其放在块的头部附近。行中的这些重复值将被替换为一个表示其中每个值的符号。从概念上讲,它看上去如下图所示,您可以看到压缩前后的块。
注意这些值是如何从行中取出并放入顶部称为“符号表”的特殊区域中的。列中的每个值都被分配一个符号,此符号将替代行内的实际值。由于符号所占空间小于实际值,因此记录大小也远远小于初始值。行中的重复数据越多,符号表和块越紧凑。
由于压缩作为触发事件发生,而不是在插入行时发生,因此在正常的 DML 进程中压缩对性能没有任何影响。压缩被触发后,对 CPU 的需求肯定会变得很高,但在其他任何时间 CPU 影响都为零,因此压缩也适用于 OLTP 应用程序,这是 Oracle 数据库 11g 中压缩的平衡点。
除了降低空间消耗外,压缩数据还将缩短网上传输时间、减少备份空间,并使在 QA 和测试中维护生产数据库的完整副本变得切实可行。
COPY 仍然存在!
与传言相反,COPY 命令仍然存在。并且它仍然是复制 LONG 数据类型的唯一方式。但由于此命令已被弃用,因此它已经跟不上 Oracle 数据库的发展步伐。
例如,它不知道存在新的数据类型 BFILE.如果您尝试复制包含 BFILE 类型列(如先前的示例中所示)的 DOCS 表:
SQL> copy to sh@oradba11 -
> replace docs_may08 -
> using select * from docs
> where creation_dt between '1-may-08' and '31-may-08';
Enter TO password:
Array fetch/bind size is 15. (arraysize is 15)
Will commit when done. (copycommit is 0)
Maximum long size is 80. (long is 80)
CPY-0012: Datatype cannot be copied
错误消息描述的是:COPY 命令无法复制 BFILE 数据类型。但如果表中包含 Long 类型列,则无法使用 INSERT /*+ APPEND */ 和 CREATE TABLE ……NOLOGGING AS SELECT …… 语句。在以下示例中,我们尝试将一个表中的某些行复制到另一个表中,第二个表中有一个定义为 LONG 类型的列:
SQL>create table mytab1 as select * from mytab where col1 = 'A';
create table mytab1 as select * from mytab
*
ERROR at line 1:
ORA-00997: illegal use of LONG datatype
SQL> insert /*+ APPEND */ into mytab
2> select * from mytab where col1 = 'A';
select * from mytab
*
ERROR at line 2:
ORA-00997: illegal use of LONG datatype
因此,要复制大量数据而不填充还原段,唯一简单的方法就是使用 COPY 命令。
导出和导入:濒临废弃
在 Oracle 数据库 10g 中引入数据泵时,预计最终将废弃传统的导出和导入工具。那么,请继续等待:在 Oracle 数据库 11g 中,这些旧工具仍然存在。由于已被弃用,这些工具不会再得到任何增强,但绝不能说它们是无用的。
就功能而言,数据泵胜过常规导入/导出许多倍,但在一种简单情况下,后者仍然非常有用:当您必须在客户端而不是服务器上创建转储文件时。由于执行操作前不必创建目录,因此在许多方面,通过常规导出/导入执行简单的数据导出可能更容易。
但是,需要再次声明的是,由于这些工具已被弃用,因此在使用时存在以下三个风险:
■ Oracle 不再为这些工具添加任何功能,因此可能不支持将来的数据类型等。
■ 这些工具可能会在未经事先声明的情况下从将来的版本中删除,您以后必须重写代码。
■ 如果您遇到错误,Oracle 支持部门可能会拒绝修复该代码。
因此,可能有必要将现有代码转换为数据泵,并且为了适应新发展,也确实应该这样做。
增量更新的全局统计信息
在分区表中,每个分区都可以有优化程序统计信息。此外,在整个表上还有与分区无关的全局统计信息,例如,整个表中不同值的数量。仅在 dbms_stats.gather_*_stats 程序发出指令时才会收集此全局统计信息,默认情况下不会收集。如果未指定全局统计信息参数,则不会收集全局统计信息,优化程序将根据分区统计信息生成全局统计信息。当然,计算得到的全局统计信息始终要比生成的统计信息精确,因此始终建议您收集全局统计信息。
但是,过去一直存在一个小问题:当分区数据变化但其他分区保持不变时,全局统计信息可能会变得陈旧。因此,即使只有一个分区发生变化,统计信息收集程序也必须遍历整个表来收集全局统计信息。
现在这个问题已不复存在。在 Oracle 数据库 11g 中,可以指示优化程序仅从更改的分区中以增量方式收集全局统计信息,而不必再次执行整表扫描。通过将用于统计信息收集的表参数 INCREMENTAL 设置为 TRUE 可完成此操作,如下所示:
begin
dbms_stats.set_table_prefs(
'SH','SALES','INCREMENTAL','TRUE');
end;
/
现在,您应该专门收集此表中粒度为 AUTO 的分区 SALES_1995 上的统计信息。
begin
dbms_stats.gather_table_stats (
ownname => 'SH',
tabname => 'SALES',
partname => 'SALES_1995',
granularity => 'AUTO'
);
end;
此统计信息收集方法指示数据库根据从新分区收集的统计信息,以增量方式更新全局统计信息。
数据泵功能改进
正如我先前提到的,自上一个版本开始,数据泵工具一直用于移动大量数据,或者对数据进行有效的“逻辑”备份。与导出/导入类似,它是独立于平台的工具(例如,可以从 Linux 导出,然后再导入 Solaris)。在 Oracle 数据库 11g 中,数据泵获得了一些增强。
数据泵存在的较大问题之一是,创建转储文件时无法对其进行压缩。在较旧的导出/导入实用程序中,这一点比较容易做到。在 Oracle 数据库 11g 中,数据泵可以在创建转储文件时对其进行压缩。这是通过在 expdp 命令行中使用参数 COMPRESSION 实现的。此参数有三个选项:
■ METDATA_ONLY — 仅压缩元数据;数据保持原样(在 Oracle 数据库 10.2 中同样可用)。
■ DATA_ONLY — 仅压缩数据;元数据保持原样。
■ ALL — 同时压缩元数据和数据。
■ NONE — 此为默认选项;不执行任何压缩。
下面说明如何压缩 UNITS_FACT 表的导出内容:
$ expdp global/global directory=dump_dir tables=units_fact dumpfile=units_fact_comp.dmp compression=all
为了便于比较,下面说明如何只导出而不压缩:
$ expdp global/global directory=dump_dir tables=units_fact dumpfile=units_fact_uncomp.dmp
现在,如果您查看所创建的文件:
$ ls -l
-rw-r----- 1 oracle dba 2576384 Jul 6 22:39 units_fact_comp.dmp
-rw-r----- 1 oracle dba 15728640 Jul 6 22:36 units_fact_uncomp.dmp
压缩比例为 100*(15728640-2576384)/15728640,大约为 83.61%!这是一个相当大的压缩比例;解压缩的转储文件为 15MB,而压缩后的转储文件为 1.5MB.如果使用 gzip 压缩转储文件:
$ gzip units_factl_uncomp.dmp
-rw-r----- 1 oracle dba 3337043 Jul 6 22:36 units_fact_uncomp.dmp.gz
压缩后的文件大约为 3.2MB,其大小是数据泵中压缩文件的二倍。因此,除了压缩可能会更加高效,解压缩也真正带来了好处。导入转储文件时,导入不必先解压缩文件;它将在读取文件时进行解压缩,从而使此过程真正变快。
数据泵中的其他两项增强功能如下:
■ 加密:可以在创建转储文件时对其进行加密。加密与 TDE(透明数据加密)使用相同的技术,并使用钱夹存储万能密钥。与 Oracle 数据库 10g 中不同,此加密将在整个转储文件上发生,而不仅仅在加密的列上发生。
■ 屏蔽:将数据从生产导入 QA 时,您可能希望确保将敏感数据(如社会保险号码等)变为乱码(将其修改成不可识别的内容)。Oracle 数据库 11g 中的数据泵可以完成此操作,方法是创建一个屏蔽函数,然后在导入期间使用此函数。
可以在安全性部分了解这两个特性。
真正联机的索引重建
是否记得在重建索引时使用的 ONLINE 子句?
alter index in_tab_01 rebuild online;
该子句可重建索引,而不影响访问它的 DML.它将跟踪正在访问的块,并在结束时使用新构建的索引合并这些块,从而完成索引重建。要完成此任务,操作必须在进程结束时获得独占锁定。虽然持续时间很短,但它仍然是一个锁定,DML 必须等待。
在 Oracle 数据库 11g 中,联机重建真正处于联机状态:它不进行独占锁定。DML 不会受影响。
使用不同的表空间存放临时表
创建全局临时表时,所占用的空间是从哪里分配的呢?它来自用户的临时表空间。通常这不会成为问题,但在某些特殊情况下,您可能要出于预期目的释放临时表空间(通常是为了排序)。有时,您可能要创建临时表,以使用位于更快、更高效磁盘上的其他临时表空间来提高数据访问速度。在这些情况下,您只能将该表空间变成用户的临时表空间。
在 Oracle 数据库 11g 中,可以使用另一个临时表空间来存放全局临时表。让我们看一看这种方案的实现方式。首先,再创建一个临时表空间:
SQL> create temporary tablespace etl_temp
2> tempfile '+DG1/etl_temp_01.dbf'
3> size 1G;
Tablespace created.
然后,使用新的表空间子句创建 GTT:
SQL> create global temporary table data_load (
2> input_line varchar2 (2000)
3> )
4> on commit preserve rows
5> tablespace etl_temp;
Table created.
现在,将在表空间 etl_temp 而不是用户的默认临时表空间 (TEMP) 上创建此临时表。
SQL*Plus 错误记录
假定您有一个名为 myscript.sql 的 SQL 脚本:
set puase on
set lines 132 pages 0 trimsppol on
select * from nonexistent_table
/
注意,此脚本中存在几处错误:第一行的“pause”和第二行的“trimspool”都存在拼写错误,而第三行的 select 语句所针对的是一个并不存在的表。在 SQL*Plus 提示符下运行该脚本时,除非您将输出假脱机,否则您之后将无法检查错误。即使假脱机输出,您也要访问物理服务器以检查假脱机文件,而这是不可能的。
Oracle 数据库 11g 提供了一个完美的解决方案:现在,您可以在一个专用表中记录来自 SQL*Plus 的错误。您应执行的第一条命令如下:
SQL> set errorlogging on
现在运行脚本:
SQL> @myscript
运行后将生成以下错误消息:
SP2-0158: unknown SET option "puase"
SP2-0158: unknown SET option "trimsppol"
select * from nonexistent_table
*
ERROR at line 1:
ORA-00942: table or view does not exist
您可能见过这些消息,也可能没见过,这取决于脚本的运行方式 — 在前台通过 SQL*Plus 提示符运行,或者在后台作为脚本调用运行。运行完脚本之后,您可以登录到数据库并检查 SPERRORLOG 表中的错误。
sql> col timestamp format a15
sql> col username format a15
sql> col script format a10
sql> col identifier format a15
sql> col statement format a20
sql> col message format a20
sql> select timestamp, username, script, statement, message
2> from sperrorlog;
TIMESTAMP USERNAME SCRIPT STATEMENT MESSAGE
--------------- --------------- ---------- -------------------- --------------------
05-JUL-08 06.08 SH myscript.s set puase on SP2-0158: unknown SE
.41.000000 PM ql T option "puase"
05-JUL-08 06.08 SH myscript.s set lines 132 pages SP2-0158: unknown SE
.41.000000 PM ql 0 trimsppol on T option "trimsppol"
05-JUL-08 06.08 SH myscript.s select * from nonexi ORA-00942: table or
.41.000000 PM ql stent_table view does not exist
注意,您是从另一个 会话中检查错误,而不是从运行脚本的会话中检查。事实上,事实上脚本已经完成,会话也已经结束。这是一项强大的功能,可以在 SQL*Plus 会话中检查发生的错误,如果没有这项功能,将无法(至少是很困难的)跟踪这些错误。
SPERRORLOG 表是专门针对此用途创建的。您还可以创建自己的表,并用 SQL*Plus 中的错误填充它。此表应按以下方式创建:
SQL> create table my_sperror_log
2 (
3 username varchar2(256),
4 timestamp timestamp,
5 script varchar2(1024),
6 identifier varchar(256),
7 message clob,
8 statement clob
9 )
10 /
Table created.
现在,您可以用此表代替默认表来记录错误。
SQL> set errorlogging on table sh.my_sperror_log;
SQL> @myscript
现在,MY_ERROR_LOG(而不是 SPERRORLOG)将保存错误日志。可以通过执行以下命令来截断所有行:
SQL> set errorlogging on truncate
有一个可选的 IDENTIFIER 子句,用于标记特定会话中的错误。假定您执行以下命令:
SQL> set errorlogging on identifier MYSESSION1
现在,如果运行脚本,将使用名为 IDENTIFIER 的列创建记录,并在列中填充值 MYSESSION1.通过执行以下查询可以提取这些记录:
select timestamp, username, script, statement, message
from sperrorlog
where identifier = 'MYSESSION1';
您将只看到该会话中的记录。如果要将多个脚本和会话中的错误分开,此功能非常有用。
缩小临时表空间
您可能已经知道,临时表空间很特殊,普通的空间管理规则可能并不适用。分配了临时段之后,将不会再回收它。这不是一个真正的问题,因为临时段(使用临时表空间)不是模式的一部分,也不会在数据库回收空间中存储。其他用户或查询可重用此空间。不管怎样,由于此空间不再回收,因此临时表空间只能不断增大。但是,我们能否对这些空间进行修剪,从而为其他表空间腾出一些空间呢?
到目前为止,唯一的办法就是删除并重新创建表空间 — 这只是小事一桩,几乎可以在保持联机的状态下完成。不过也存在一点“小问题”:如果要求正常运行时间必须达到百分之百时怎么办?在 Oracle 数据库 11g 中,通过缩小临时表空间可以很容易实现这一点。
下面说明如何缩减表空间 TEMP1:
alter tablespace temp1 shrink space;
此命令回收表空间中所有的未用段,从而缩小了表空间。完成上述操作后,可以通过 DBA_TEMP_FREE_SPACE 视图查看当前已分配的空间和可用空间是多少。
SQL> select * from dba_temp_free_space;
TABLESPACE_NAME TABLESPACE_SIZE ALLOCATED_SPACE FREE_SPACE
------------------------------ --------------- --------------- ----------
TEMP 179306496 179306496 178257920
在相对静止的数据库中,缩小操作几乎可以将临时表空间缩小为空。这当然不会成为真实情况;由于后续活动将扩大表空间,因此您可能希望在内部留出一些空间,假定为 100MB.可以执行以下命令:
SQL> alter tablespace temp shrink space keep 100m;
Tablespace altered.
SQL> select * from dba_temp_free_space;
TABLESPACE_NAME TABLESPACE_SIZE ALLOCATED_SPACE FREE_SPACE
------------------------------ --------------- --------------- ----------
TEMP 105906176 1048576 104857600
仅留下 100MB,其余空间都被释放。此方法有助于在各种表空间中管理空间。现在,您可以从某个临时表空间中借用一些空间,来临时提供给其他表空间(并非故意使用双关语)。如果日后不再需要此空间,可将其还给临时表空间。将此特性与用于全局临时表的表空间结合起来使用时,可以解决临时表空间中的许多空间管理难题。
SQL*Plus 显示 BFILE
Oracle 数据库中的 BFILE 数据类型存储指向外部文件的指针,而不存储文件自身的内容。它具有以下特定用途:当用户可以访问文件中的数据时可以节省数据库空间,这对于某些应用程序(如使用内容和多媒体丰富的数据库的应用程序)来说非常有用。
如果表中有一个 BFILE 类型列,您要在 SQL*Plus 中选择表的某些行,这在过去常常会发生错误。在 Oracle 数据库 11g 中,SQL*Plus 将文件位置作为列值显示。
让我们来看一个示例。首先,必须创建一个用于存储 BFILE 的目录。
SQL> create directory doc_dir as '/u01/oracle/docs';
Directory created.
现在创建表。
SQL> create table docs
2 (
3 doc_id number(20),
4 doc_file bfile,
5 doc_type varchar2(10)
6 );
Table created.
创建行。
SQL> insert into docs values
2 (
3 1,
4 bfilename('DOC_DIR','metric_daily_report.pdf'),
5 'PDF'
6 );
1 row created.
现在,如果在 SQL*Plus 中选择此行:
SQL> col doc_file format a50
SQL> select * from docs;
DOC_ID DOC_FILE DOC_TYPE
---------- -------------------------------------------------- ----------
1 bfilename('DOC_DIR', 'metric_daily_report.pdf') PDF
DOC_FILE 列下的输出(为 BFILE 类型)显示文件位置,而不显示错误消息。
内存中的参数文件
考虑如下情形:在诊断某个数据库问题期间,您修改了很多参数,这些参数都位于内存中。后来,您忘记更改了哪些参数。除非您记得将这些参数放入初始化参数文件(pfile 或 spfile)中,否则这些更改将会丢失。您很有可能未将这些参数放入该文件,因为您正在测试这些值,尚未确定要使用哪个特定值。当然,您可以查看警报日志并找出所作的全部更改,但这一过程既费力又容易出错。
在 Oracle 数据库 11g 中,可以使用一个非常简单的命令,通过内存中的参数值来创建 pfile 或 spfile.
SQL> create spfile from memory;
File created.
SQL> create pfile from memory;
File created.
这将使用内存中的值创建 spfile 或 pfile.pfile 文件的顶部将包含如下条目:
# Oracle init.ora parameter file generated by instance ODEL11 on 08/28/2007 14:52:14
这将捕获内存中已更改的参数,可以为您节省大量精力,并会大大降低风险。此特性还允许您使用其他名称创建 pfile,然后将当前 pfile 与所生成的文件进行比较,以查看更改了哪些参数。
SQL> create pfile='/tmp/a' from memory;
此语句将创建一个名为 /tmp/a 的 pfile.现在,在 Unix 中,可以使用简单的 diff 命令显示这两个文件之间的差异。
谨慎重置
在性能优化过程中,您要检查直接在 spfile 上更改几个动态初始化参数所造成的影响,突然您担心之后会找不到所作的更改。由于这些内容是在 spfile 中更改的,因此您不能指望 spfile 会告诉您更改了哪些值。
没关系,可以使用以下方法:ALTER SYSTEM RESET 命令将值重置为默认值,覆盖您在 spfile 中所作的更改:
alter system reset license_max_sessions;
早期版本中也提供了此命令,但存在一个根本区别:在早期版本中,它需要在 RAC 数据库中使用 SID 子句。如果您要在所有实例上重置,应指定 SID='*' 子句。在 Oracle 数据库 11g 中,SID 子句是可选的,默认值为所有实例。因此,在以前版本中如果忽略该子句将会出错;现在则不会出现这种情况,但效果可能并不如您所愿。因此,重置时要谨慎。
实时 SQL 监视
此特性给性能诊断带来了巨大的飞跃。考虑如下情形:有人正在运行一组 SQL 语句(可能在 PL/SQL 代码内部)。但是,如何知道访问路径中的每个步骤占用了多少资源(CPU、I/O 等)呢?可以使用 Trace Analyzer 或普通的旧式 tkprof 来跟踪会话或分析跟踪文件,但这只能在事后进行。您肯定希望能够实时了解会话中发生的情况,不是吗?
Oracle 数据库 11g 中提供了一个新特性“实时 SQL 监视”,确实能够做到名副其实:它允许您实时查看正在执行的 SQL 的不同衡量标准。统计信息通过动态性能视图 V$SQL_MONITOR 显示,每秒钟刷新一次。
作为演示,我们来运行一个大型查询,并监视实时统计信息。我们知道,运行大型查询的会话的 SID 为 103.从视图中进行选择时,我使用了 Tom Kyte 著名的 print_table 工具,为了提高可读性,此工具以垂直格式显示输出。
SQL> exec print.tbl('select * from v$sql_monitor where sid = 103')
KEY : 476741369968
STATUS : EXECUTING
FIRST_REFRESH_TIME : 07-jul-2008 14:13:38
LAST_REFRESH_TIME : 07-jul-2008 14:26:27
REFRESH_COUNT : 48043
SID : 103
PROCESS_NAME : ora
SQL_ID : 2xj1nram1k1x0
SQL_EXEC_START : 07-jul-2008 14:13:31
SQL_EXEC_ID : 16777216
SQL_PLAN_HASH_VALUE : 1759042790
SQL_CHILD_ADDRESS : 38837734
SESSION_SERIAL# : 32668
PX_SERVER# :
PX_SERVER_GROUP :
PX_SERVER_SET :
PX_QCINST_ID :
PX_QCSID :
ELAPSED_TIME : 42638722
CPU_TIME : 9199624
FETCHES : 48032
BUFFER_GETS : 3238
DISK_READS : 12096
DIRECT_WRITES : 13419
APPLICATION_WAIT_TIME : 0
CONCURRENCY_WAIT_TIME : 134534
CLUSTER_WAIT_TIME : 0
USER_IO_WAIT_TIME : 148436
PLSQL_EXEC_TIME : 0
JAVA_EXEC_TIME : 0
-----------------
大多数列都具有自我说明性:SQL_ID — SID 正在执行的 SQL 语句的 sql_id;STATUS — SQL 现在的状态,显示此时正在执行该语句;SQL_EXEC_START — 开始时间;等等。CPU_TIME、DISK_READS 和 DIRECT_WRITES 等列显示其同名的衡量指标。如果继续执行该查询,您将会看到这些衡量标准得到了更新。
另一个视图 V$SQL_PLAN_MONITOR 显示所执行的 SQL 语句的优化程序计划,并实时进行更新。下面说明如何使用该视图实时查看计划中的各个步骤以及关联的统计信息。
select plan_line_id,
plan_operation,
plan_options,
output_rows
from v$sql_plan_monitor
where sid = 103
order by plan_line_id;
PLAN_LINE_ID PLAN_OPERATION PLAN_OPTIONS OUTPUT_ROWS
------------ ------------------------------ ------------------------------ -----------
0 SELECT STATEMENT 809994
1 HASH GROUP BY 809994
2 HASH JOIN 918845
3 PART JOIN FILTER CREATE 1826
4 TABLE ACCESS FULL 1826
5 HASH JOIN 918845
6 TABLE ACCESS FULL 503
7 HASH JOIN 918845
8 TABLE ACCESS FULL 72
9 HASH JOIN 918845
10 TABLE ACCESS FULL 5
11 HASH JOIN 918845
12 TABLE ACCESS FULL 55500
13 PARTITION RANGE JOIN-FILTER 918845
14 TABLE ACCESS FULL 918845
与前面的视图一样,如果您重新执行查询,将会看到衡量标准已更新。这两个视图允许您实时查看该 SQL 的处理过程。
实时 SQL 监视另一个有用的部分是 SQL 监视报表。使用此报表,您可以得到一个包含 SQL 各种衡量标准和计划步骤的可视报表。此报表是作为 DBMS_SQLTUNE 程序包中 REPORT_SQL_MONITOR 函数的 CLOB 输出生成的。下面说明如何调用该函数:
SQL> set long 99999 lines 3000 pages 0 trimspool on
SQL> select dbms_sqltune.report_sql_monitor (
2 event_detail => 'YES',
3 report_level => 'ALL',
4 type => 'HTML'
5 )
6 from dual;
将输出假脱机到名为 rep1.html 的文件并运行 SQL.一段时间后,将输出假脱机到新文件 rep2.html 后再次运行此 SQL.最后,在查询将输出假脱机到 rep3.html 之后运行此 SQL.每个报表文件都是当时 SQL 实时衡量标准的快照。通过在三个不同时间获取报表可以跟踪进度。在 Web 浏览器中打开其中一个文件,显示如下:
从图中可以看到显示其衡量标准的 SQL 语句。在左上方可以看到有关 SQL 的元数据 — 开始时间、上次刷新时间等。在右侧可以看到不同颜色的横条,表示不同的衡量标准。如果将鼠标悬停在这些横条上,您会看到该横条的描述及其所表示的值。
屏幕底部显示查询的优化程序计划以及每个步骤所花费的时间,并将这些信息归纳到“CPU 活动”、“等待”等类别中。彩色横条显示每个度量标准的相对值。如果将鼠标悬停在这些横条上,您会看到每个度量标准的值和时间段。
此报表仅仅是实时 SQL 监视视图的快照,此视图以前曾以图形格式出现过。图形化表示的数据有助于您了解查询的各个组件,并衡量每个组件所花费的时间,从而使性能诊断更加容易。
结束语
我花了 20 周时间带领您快速浏览 Oracle 数据库 11g 中引入的新特性,这项工作到此就要结束了。同其他作者一样,我力求维持深度和广度之间的微妙平衡。但在前面有关 Oracle 数据库 10g 第 1 版和第 2 版的文章系列中,您的反馈明确而清晰:您喜欢我基于示例、以讲故事的形式进行阐述,因此我在本系列中依然采用了这种格式。
谨向对本系列文章进行验证的审阅者致以诚挚的谢意!我衷心感谢 Justin Kestelyn,是他的支持和帮助激励我成功地完成了这项工程。最后,我还要衷心感谢亲爱的读者朋友,我为您所做的一切都是值得的。
- ››oracle 恢复误删除的表和误更新的表
- ››Oracle分页查询排序数据重复问题
- ››Oracle创建dblink报错:ORA-01017、ORA-02063解决
- ››Oracle 提高SQL执行效率的方法
- ››Oracle 动态查询,EXECUTE IMMEDIATE select into...
- ››Oracle 11g必须开启的服务及服务详细介绍
- ››oracle性能34条优化技巧
- ››oracle数据库生成随机数的函数
- ››Oracle 数据库表空间容量调整脚本
- ››oracle单库彻底删除干净的方法
- ››Oracle创建表空间、创建用户以及授权、查看权限
- ››oracle 中 UPDATE nowait 的使用方法
更多精彩
赞助商链接