您的统计信息是否陈旧?不要再等待了
						
				
				
						
						 
				
						
								    大部分DBA都知道,Oracle 10g 版本最后不再支持(而不是反对)基于规则的优化器 (RBO)。考虑到这种期待已久的发展即将发生,很多 Oracle9i 数据库商店升级到基于开销的优化器 (CBO),以便进入支持循环并利用查询重写和分区修剪等高级特性。但是,问题在于统计信息 — 或者说在于缺少统计信息。 
				
				
						
						 
				
						
								    因为 CBO 依靠准确的(或者说比较准确的)统计信息来产生优化的执行路径,所以 DBA 需要确保定期收集统计信息,创建另一个执行核对清单。在 10g 之前,这一过程可能由于多种原因而徒劳无功。这种困难导致产生了一种理论,即 CBO 具有“自己的思想” — 这意味着会有随意更改执行路径的行为! 
				
				
						
						 
				
						
								    在 10g 中已经消除了很多这类的顾虑,它能够自动收集统计信息。在 Oracle9i 中,您可以通过打开表监视选项 (ALTER TABLE ...MONITORING) 然后检查这些表的视图 DBA_TAB_MODIFICATIONS,检查表中的数据是否已明显更改过。 
				
				
						
						 
				
						
								    在 10g 中,已不再使用 MONITORING 语句了。而通过设置初始化参数 STATISTICS_LEVEL 为 TYPICAL 或 ALL,就可以自动收集统计信息。(默认值为 TYPICAL,因此可以随即启用自动收集统计信息的功能。)Oracle 数据库 10g 具有一个预定义的调度程序(您在第 19 周中已经学习过调度程序)作业,名称为 GATHER_STATS_JOB,它由 STATISTIC_LEVEL 参数的适当数值所激活。 
				 
				
						
						 
				
						
								    统计信息的收集是资源相当密集的工作,因此您可能希望确保它不影响数据库的正常操作。在 10g 中,您可以使这一工作自动完成:可对一个名为 AUTO_TASK_CONSUMER_GROUP 的特定资源用户组进行预定义,用于自动执行一些任务,比如收集统计信息。该用户组确保这些统计信息收集作业的优先权低于默认用户组,因此减少或消除了自动化任务占用整个机器的风险。 
				
				
						
						 
				
						
								    如果希望将参数 STATISTIC_LEVEL 设为 TYPICAL 却不希望自动收集统计信息时该怎么办?很简单。只需使用以下语句来禁用调度程序作业即可: 
				
				
						
						 
				
						BEGIN
DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');
END;
				
				
						
						
								    那么您为什么要这样做呢?有很多原因 — 其中一个原因是,虽然表中大部分行发生了变化,但分布情况可能没有改变,这在数据仓库中很常见。在这种情况下,您不希望再次收集统计信息,而只是希望重用原来的统计信息。另一个原因可能是您正在使用分区交换功能来刷新物化视图 (MV),并且不希望收集关于物化视图的统计信息,因为关于被交换表的统计信息也会被导入。但是,您也可以将特定的表排除在自动统计信息收集作业之外,而不需要禁止整个作业。 
				
				
						
						 
				
						
						 
				
						
								统计信息历史 
						
				
				
						
						 
				
						
								    在优化器收集统计信息时可能出现的复杂情况之一是执行计划的改变 — 也就是说,原来的优化方法在收集统计信息之前一直工作良好,但是在此之后,由于新收集的统计信息产生了不良计划,导致查询突然出错。这种问题并不少见。 
				
				
						
						 
				
						
								    为避免这种灾难,统计信息的收集作业在收集新信息之前保存当前的统计信息。如果出现问题,您总可以返回到原有的统计信息,或者至少可以检查二者之间的不同之处,以便于解决问题。 
				
				
						
						 
				
						
								    例如,假设在 5 月 31 日晚上 10:00 开始运行表 REVENUE 上的统计信息收集作业,而随后查询的性能变差。Oracle 保存了原有的统计信息,您可以通过执行以下命令重新获取这些信息: 
				
				
						
						 
				
						begin
dbms_stats.restore_table_stats (
'ARUP',
'REVENUE',
'31-MAY-04 10.00.00.000000000 PM -04:00');
end;
				
				
						
						 
				
						
								    此命令恢复到 5 月 31 日晚上 10:00 为止的统计信息,时间信息是以 TIMESTAMP 数据类型提供。这样您就立即还原了由新的统计信息收集程序所作的更改。 
				
				
						
						 
				
						
								    您能够恢复的时间长度是由保留参数所决定的。要查看当前的保留参数,可使用以下查询: 
				
				
						
						 
				
						SQL> select DBMS_STATS.GET_STATS_HISTORY_RETENTION from dual;
				
				
						
						 
				
						GET_STATS_HISTORY_RETENTION
---------------------------
                         31
				
				
						
						 
				
						
								    在本示例中表示可以保存相当于 31 天的统计信息,但并不能予以保证。要了解统计信息所覆盖到的确切时间和日期,只需使用以下查询: 
				
				
						
						 
				
						SQL> select DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY from dual;
				
				
						
						 
				
						GET_STATS_HISTORY_AVAILABILITY
---------------------------------------------------------------------
17-MAY-04 03.21.33.594053000 PM -04:00
				
				
						
						 
				
						
								    该查询表明可用的最陈旧统计信息日期为 5 月 17 日凌晨 3:21。 
				
				
						
						 
				
						
								    您可以通过执行内建的函数将保留时间设为不同的值。例如,要将其设为 45 天,可使用: 
				
				
						execute DBMS_STATS.ALTER_STATS_HISTORY_RETENTION (45)
				
				
						
						 
				
						
						 
				
						
								有保证的还原保留功能 
						
				
				
						
						 
				
						
								    自动还原保留功能是在 Oracle9i 中推出的,它极其有助于减少令人讨厌的 ORA-1555 "Snapshot Too Old" 错误的出现机率。但是这些错误还是会出现,虽然其数量已大大减少。这是为什么呢? 
				
				
						
						 
				
						
								    要回答这个问题,您需要了解还原段是如何工作的。当 Oracle 内部的数据发生变化时,高速缓存中的块(在 SGA 中)立即发生变化,而过去的映像被存储在还原段中。当事务提交时,不再需要旧的映像,因此可以重用它们。如果还原段中的所有空间都被活动的事务所使用,则 Oracle 将尝试重用段中最陈旧的范围(这一进程称为“折返”,如 V$ROLLSTAT 视图中的 WRAPS 列所示)。但是,在某些情况下,特别是在长时间运行的事务中,段将会扩展,为活动的事务提供空间,如 V$ROLLSTAT 中的列 EXTENDS 所示。如果查询需要使用还原段范围中的数据来创建数据的一致性视图,但是该范围已经被重用,则查询产生 ORA-1555 错误。 
				
				
						
						 
				
						
								    初始化参数 UNDO_RETENTION_PERIOD 指定必须保留多少还原数据(以秒为单位)。通过指定时间,Oracle 确保不重用陈旧的还原范围,即使这些范围处于不活动的状态,或它们在还原保留时间内已经被更改,Oracle 也不会重用它们。这种方法减少了不活动范围以后可能被查询所意外重用的机率,这种重用会导致产生 ORA-1555 错误。 
				
				
						
						 
				
						
								    但是,虽然 UNDO_RETENTION_PERIOD 指定了可以保留多少还原数据,它并不保证得到这种结果。当段不能扩展范围时,最陈旧的不活动范围被重用,以满足当前事务的需要。因此,当查询这些范围时,某些与更改事务无关的长时运行的查询可能会失败,并产生 ORA-1555 错误。 
				
				
						
						 
				
						
								    这个问题在 10g 中得到了解决:当您创建还原表空间时,您现在可以指定对还原保留功能的“保证”。下面是一个例子: 
				
				
						
						 
				
						CREATE UNDO TABLESPACE UNDO_TS1
DATAFILE '/u01/oradata/proddb01/undo_ts1_01.dbf'
SIZE 1024M
RETENTION GUARANTEE;
				
				
						
						 
				
						
								    请注意最后的子句,它使还原表空间保证了对未过期还原范围的保留。通过对现有还原表空间进行 ALTER 操作,也可以使其作出保证,如下所示: 
				
				
						
						 
				
						ALTER TABLESPACE UNDO_TS2 RETENTION GUARANTEE;
				
				
						
						 
				
						
								    如果您不希望对保留作出保证(Oracle9i 中的行为)该怎么办?那么,可执行以下操作: 
				
				
						
						 
				
						ALTER TABLESPACE UNDO_TS2 RETENTION NOGUARANTEE;
				
				
						
						 
				
						
								    您可以使用以下语句来验证表空间是否已经保证了还原保留功能: 
				
				
						
						 
				
						SELECT RETENTION
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'UNDO_TS1';
				
				
						
						 
				
						
						 
				
						
								端到端跟踪 
						
				
				
						
						 
				
						
								    诊断性能问题的一种常见方法是启用 sql_trace 来跟踪数据库调用,然后使用 tkprof 等工具来分析输出。但是,这种方法在具有共享服务器体系结构的数据库中具有严重的局限性。在这种配置中,创建了若干个共享服务器进程,为用户的请求提供服务。当用户 BILL 连接数据库时,调度程序将连接传递到一个可用的共享服务器进程。如果没有可用的共享服务器进程,则创建一个新进程。如果开始跟踪该会话,则会跟踪由共享服务器进程所进行的调用。 
				
				
						
						 
				
						
								    现在假设 BILL 的会话变为空闲状态,而 LORA 的会话变为活动状态。此时最初为 BILL 提供服务的共享服务器被分配给 LORA 的会话。这样,发出的跟踪信息不是来自 BILL 的会话,而是来自 LORA 的会话。当 LORA 的会话变为非活动状态时,该共享服务器可以被分配给另外的活动会话,这个会话将具有完全不同的信息。 
				
				
						
						 
				
						
								    在 10g 中,通过使用端到端跟踪,已经有效地解决了这一问题。在这种情况下,跟踪不仅根据会话进行,还可根据客户标识符等可识别的名称来进行。一个名为 DBMS_MONITOR 的新程序包可用于此目的。 
				
				
						
						 
				
						
								    例如,您可能希望跟踪所有具有标识符 account_update 的会话。为建立跟踪,您可以执行: 
				
				
						
						 
				
						exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('account_update');
				
				
						
						 
				
						
								    此命令开始跟踪所有具有标识符 account_update 的会话。当 BILL 连接数据库时,他可以使用以下语句来设置客户标识符: 
				
				
						
						 
				
						exec DBMS_SESSION.SET_IDENTIFIER ('account_update')
				
				
						
						 
				
						
								    跟踪对于具有标识符 account_update 的会话起作用,因此以上的会话将会被跟踪,并会在用户卸出目标目录中产生一个跟踪文件。如果另一个用户连接数据库并将其客户标识符设置为 account_update,则自动跟踪该会话,不需要在代码中设置任何其他的命令。直到使用以下命令禁用跟踪功能前,将跟踪所有具有客户标识符 account_update 的会话: 
				
				
						
						 
				
						exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('account_update');
				
				
						
						 
				
						
								    作为结果的跟踪文件可以由 tkprof 进行分析。但是,每个会话都产生不同的跟踪文件。为了正确地诊断故障,我们关心合并的跟踪文件而不是单独的跟踪文件。我们如何获得合并的跟踪文件呢? 
				
				
						
						 
				
						
								    很简单。利用一种称为 trcsess 的工具,您可以将那些与客户标识符 account_update 相关的信息提取到一个单独的文件中,通过 tkprof 可以处理该文件。在以上的案例中,您可以转到用户卸出目标目录中并运行: 
				
				
						
						 
				
						trcsess output=account_update_trc.txt clientid=account_update *
				
				
						
						 
				
						
								    此命令创建一个名为 account_update_trc.txt 的文件,该文件与常规的跟踪文件类似,但它只包含与那些具有客户标识符 account_update 的会话相关的信息。该文件可以使用 tkprof 进行处理,以获得经过分析的输出。 
				
				
						
						 
				
						
								    将这种方法和前一种更困难的跟踪信息收集方法对比此外,跟踪是由客户标识符这样的变量来启用和禁止的,而不需要从该会话中调用 alter session set sql_trace = true。同一程序包中的另一个过程 SERV_MOD_ACT_TRACE_ENABLE 能够在其他组合方式中启用跟踪功能,如用于特定服务、模块或操作的组合,可以利用 dbms_application_info package 来进行设置。 
				
				
						
						 
				
						
						 
				
						
								数据库的使用
						
				
				
						
						 
				
						
								    您的 Oracle 销售代表将会确认,分区功能是要额外购买的选件,而在如今这个控制成本的时代,您可能希望了解用户是否使用该选件 — 如果使用,使用的频率怎样。 
				
				
						
						 
				
						
								    不必依赖于用户的回答,只需查询数据库即可。自动工作负载信息库(在第 6 周中有介绍)收集所有已安装特性的使用情况信息,尽管每周只收集一次。 
				
				
						
						 
				
						
								    两个非常重要的视图显示了数据库的使用模式。其中之一是 DBA_HIGH_WATER_MARK_STATISTICS,它显示当前数据库中使用的每个特性的最大值。以下是一个示例输出。 
				
				
						
						 
				
						NAME             HIGHWATER LAST_VALUE DESCRIPTION
--------------- ---------- ---------- ----------------------------------------------------------
USER_TABLES            401        401 Number of User Tables
SEGMENT_SIZE    1237319680 1237319680 Size of Largest Segment (Bytes)
PART_TABLES             12          0 Maximum Number of Partitions belonging to an User Table
PART_INDEXES            12          0 Maximum Number of Partitions belonging to an User Index
USER_INDEXES           832        832 Number of User Indexes
SESSIONS                19         17 Maximum Number of Concurrent Sessions seen in the database
DB_SIZE         7940079616 7940079616 Maximum Size of the Database (Bytes)
DATAFILES                6          6 Maximum Number of Datafiles
TABLESPACES              7          7 Maximum Number of Tablespaces
CPU_COUNT                4          4 Maximum Number of CPUs
QUERY_LENGTH          1176       1176 Maximum Query Length
				
				
						
						 
				
						
								    可以看到,此视图显示了一些有关数据库使用情况的有价值的信息 — 如用户创建了一个最多可拥有 12 个分区的表,但现在却没有使用一个分区 (LAST_VALUE = 0)。这些信息在关闭状态下也持续存在,这对于计划操作非常有用,比如移植到不同的主机。 
				
				
						
						 
				
						
								    但是,上述视图仍然没有回答我们所有的问题。它只是告诉我们曾经创建了具有 12 个分区的表,但没有说明该特性的最后一次使用时间。另一个视图 DBA_FEATURE_USAGE_STATISTICS 显示了数据库各种特性的使用情况,它可以回答这个问题。以下是该视图分区特性的显示情况,其中的列以纵向格式显示。 
				
				
						
						 
				
						DBID                          : 4133493568
NAME                          :Partitioning
VERSION                       : 10.1.0.1.0
DETECTED_USAGES               : 12
TOTAL_SAMPLES                 : 12
CURRENTLY_USED                :FALSE
FIRST_USAGE_DATE              :16-oct-2003 13:27:10
LAST_USAGE_DATE               :16-dec-2003 21:20:58
AUX_COUNT                     :
FEATURE_INFO                  :
LAST_SAMPLE_DATE              :23-dec-2003 21:20:58
LAST_SAMPLE_PERIOD            : 615836
SAMPLE_INTERVAL               : 604800
DESCRIPTION                   :Oracle Partitioning option is being used -
there is at least one partitioned object created.
				
				
						
						 
				
						
								    如本视图所示,现在数据库中没有使用分区特性(列 CURRENTLY_USED 的值为 FALSE),最后一次使用该特性的时间是 2003 年 12 月 16 日晚上 9:20。使用信息的采样时间为 604,800 秒或者说是 7 天,示于列 SAMPLE_INTERVAL 中。列 LAST_SAMPLE_DATE 显示了对该使用信息的最后采样时间,表明此信息的新旧程度。 
				
				
						
						 
				
						
								    除了命令行接口之外,企业管理器 10g 还显示以下信息。在 EM 中,在 Administration 标签处单击 Configuration Management 下方的“Database Usage Statistics”链接。(参见图 1 和图 2。) 
				
				
						
						 
				
				
						
						图 1:数据库使用情况的统计信息页面
				
				
						
						 
				
				
						
						图 2:数据库使用情况的统计信息;下钻特性 
				
				
						
						 
				
						
						 
				
						
								更容易和更安全的加密
						
				
				
						
						
								    还记得程序包 DBMS_OBFUSCATION_TOOLKIT (DOTK) 吗?它是 Oracle9i 以及更低版本的数据库中唯一可用的加密方法。尽管该程序包对于大部分数据库而言已经足够了,但是象大多数安全产品一样,它很快就无法应付那些涉及高度敏感信息的高超的黑客攻击。在所缺少的功能中,一个值得注意的功能是对高级加密标准 (AES) 的支持,该标准是以前的数字加密标准 (DES) 以及三倍 DES (DES3) 的一个功能更强的后继标准。 
				
				
						
						 
				
						
								    在 10g 中,一种更加完善的加密方法 DBMS_CRYPTO 用于处理这种问题。这个内建的程序包提供了 DOTK 中缺少的所有功能,并且对现有的函数和过程进行了增强。例如,DBMS_CRYPTO 可以使用新的 256 位 AES 算法进行加密。函数 ENCRYPT(也将其作为过程而超载)接受以下的几个参数: