Automatic tuning of db_file_multiblock_read_count

db_file_multiblock_read_count曾经是一个经过热烈讨论的初始化参数。该参数只有在对表或者索引进行Full Scan的时候才起作用。

在Oracle10gR2以前的版本中,DBA必须根据db_block_size参数,以及应用系统的特性,来调整db_file_multiblock_read_count参数。该参数值将影响CBO在该产生何种SQL执行计划上的判断。

我们知道如下的公式,其中max I/O chunk size跟操作系统有关,但是Oracle文档中也指出大多数操作系统上该值为1M。

db_file_multiblock_read_count = max I/O chunk size / db_block_size

在Oracle10gR2之后的版本(10gR2和11g)中,Oracle数据库已经可以根据系统的IO能力以及Buffer Cache的大小来动态调整该参数值,Oracle建议不要显式设置该参数值。但是根据Oracle官方文档对于此参数的解释:

Note that if the number of sessions is extremely large the multiblock read count value is decreased to avoid the buffer cache getting flooded with too many table scan buffers.
Even though the default value may be a large value, the optimizer will not favor large plans if you do not set this parameter. It would do so only if you explicitly set this parameter to a large value.

因此建议对于已知确实将进行大量全表扫描的OLAP系统,还是应该直接设置为较大的值。

Automatic Statistics Gathering

在Oracle10g中引入的优化器统计信息(Optimizer Statistics)自动收集,是一个看上去很不错的功能,但是在实际应用中却往往没有起到相应的效果,甚至在某些系统中我们会建议禁用这个功能。

阐述一些该功能的相关知识点。

1. Automatic Statistics Gathering是由Scheduler调度GATHER_STATS_JOB作业来完成的,在GATHER_STATS_JOB作业中则调用DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC存储过程。

2. 该作业在创建数据库的自动创建,并且设置为每天晚上10点到第二天早上6点和周六周日的全天为运行窗口期。在运行窗口期内,该作业都会运行,根据stop_on_window_close属性来决定,如在窗口期结束以后,该作业如果还没有运行完毕,是继续运行还是结束运行。

3. GATHER_DATABASE_STATS_JOB_PROC是内部的存储过程,基本上跟DBMS_STATS.GATHER_DATABASE_STATS的功能一样,但是有内部的优先顺序考虑,更新越多的表将会越优先收集统计信息。

4. 收集统计信息的表对象是,之前从来没有收集过的或者是更新的(包括insert,update,delete,truncate)记录数超过当前总记录数10%的表。记录数的更改量由Oracle数据库自动监控,在初始化参数statistics_level设置为TYPICAL或者ALL时,自动监控即会生效。

5. 在USER_TAB_MODIFICATIONS表中记录了所有被监控的表的数据量更改信息。该信息的更新将会稍微滞后于真实的修改,可以通过DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO存储过程来立刻将更改的信息更新到USER_TAB_MODIFICATIONS表中。对于更新之后再rollback的记录,仍然算为已经受影响的记录,Oracle不会在rollback之后再去更新USER_TAB_MODIFICATIONS表。

SQL> select * from user_tab_modifications where table_name=’EMP’;

no rows selected

SQL> select count(*) from emp;

COUNT(*)
———-
14

SQL> update emp set sal=sal+100;

14 rows updated.

SQL> select * from user_tab_modifications where table_name=’EMP’;

no rows selected

SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO();

PL/SQL procedure successfully completed.

SQL> select inserts,updates,deletes from user_tab_modifications where table_name
=’EMP’;

INSERTS UPDATES DELETES
———- ———- ———-
0 14 0

SQL> rollback;

Rollback complete.

SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO();

PL/SQL procedure successfully completed.

SQL> select inserts,updates,deletes from user_tab_modifications where table_name
=’EMP’;

INSERTS UPDATES DELETES
———- ———- ———-
0 14 0

SQL>

6. 在Oracle10g版本(包括最新的10.2.0.4)中没有已知的修改10%这个阀值的方法。但是在Oracle11g中则提供了SET_TABLE_PREFS等函数。

以下命令将指定表的STALE默认值从10%改为5%,该值可以从新的dba_tab_stat_prefs数据字典中查询获得。

–仅限于Oracle11g版本
BEGIN
DBMS_STATS.SET_TABLE_PREFS ( ownname =>’KAMUS’, tabname =>’T1′, pname =>’STALE_PERCENT’, pvalue =>’5′);
END;
/

SQL> select * from dba_tab_stat_prefs;

OWNER TABLE_NAME PREFERENCE_NAME PREFE
———- ———- ——————– —–
KAMUS T1 STALE_PERCENT 5

7. 在Oracle10g中运行以下命令,可以禁用统计信息自动收集功能。
BEGIN
DBMS_SCHEDULER.DISABLE(‘GATHER_STATS_JOB’);
END;
/

Learning ODI – Start Scheduler Agent

对于设置ODI的定时执行场景,需要启动Scheduler Agent,在一个新的ODI安装完毕之后,默认的odiparams.bat文件中设置的是连接DEMO环境的数据库连接配置,如果我们在自己的数据库里创建了Master Repository和Work Repository,那么需要修改连接参数。

在我的测试环境中,我使用的是自己机器上Oracle 11g数据库,实例名是orcl11g,则需要做如下修改:

set ODI_SECU_DRIVER=oracle.jdbc.driver.OracleDriver
set ODI_SECU_URL=jdbc:oracle:thin:@localhost:1521:orcl11g
set ODI_SECU_USER=snpm
set ODI_SECU_ENCODED_PASS=b9yX4CpBkdmaP8Y3mYbaoye2p
set ODI_SECU_WORK_REP=WORKREP1
set ODI_USER=SUPERVISOR
set ODI_ENCODED_PASS=hZypfAZQf.Yo8VWVI6HZzc 

其中:
ODI_SECU_USER需要设置为创建Master Repository时候的用户名,在这里是snpm。
ODI_SECU_ENCODED_PASS需要用agent实用程序加密一下,用法是agent encode %PASSWORD%。
ODI_SECU_WORK_REP设置为创建Work Repository时候起的名字。
ODI_USER默认是SUPERVISOR,这是连接ODI的用户名。
ODI_ENCODED_PASS默认是SUNOPSIS,也需要用agent encode加密之后的值。

设置完毕,启动Scheduler Agent,会遇到下面的错误:

java.lang.Exception: Agent is not declared in Topology Manager

我们还需要在Topology Manager -> Physical Architecture -> Agents里面创建一个Agent,填写Agent的名字,监听的机器,端口。如果需要设置Schedule,还需要在Topology Manager -> Logical Architecture -> Agents里面再创建一个Agent,将刚才创建的Physical Agent和此Logical Agent绑定在一起。

然后,在Designer -> Projects -> Scenarios -> Scheduling中创建一个执行计划,之后再次启动Scheduler Agent就OK了。

C:\OraODI\oracledi\bin>agentscheduler "-port=20910" "-NAME=myFirstAgent"
A JDK is required to execute Web Services with OracleDI. You are currently using a JRE.
OracleDI: Starting Scheduler Agent ...
Starting Oracle Data Integrator Agent...
Version : 10.1.3.4.0 - 30/10/2007
Agent in scheduling mode
Number of items for scheduled executions:0
08/17/2008 02:58:09 PM(main): Server Launched
Aug 17, 2008 3:06:27 PM com.sunopsis.j.s a
INFO: Start Thread[1001@2008/08/17_03:06:27:000,5,main] @ Aug 17, 2008 3:06:27 PM

最后一行显示了在Schedule中定义的计划被执行成功。

在Windows操作系统中可以把Agent程序设置为Service,通过以下命令设置,其中倒数两个参数分别为Physical Agent Name和Agent Port:

agentservice.bat -i -s myFirstAgent 20910

运行成功之后,将会产生OracleDI Agent Scheduler myFirstAgent这样命名的Windows服务。

通过以下命令可以删除创建的服务:

agentservice.bat -r -s myFirstAgent