optimizer_index_cost_adj的测试 I

optimizer_index_cost_adj的测试。

关于optimizer_index_cost_adj这个参数,起初并没有太多注意,在9i下其default100一直工作得很合适。

不过偶然看到一个家伙把DB9i->10g后,默认的100使得很多SQLexecution plan发生了变化。这说明10g9iCBO算法是有变化的。因此对这个参数产生了兴趣,

[@more@]

就按Tim Gorman的观点,每个系统有它自己合适的optimizer_index_cost_adj的值。

下面来看生产系统Eoptimizer_index_cost_adj的值应该设多少。

生产环境是RHEL4up4+Oracle 9i.

按照Tim Gorman的算法。这个值大致应该是V$system_event中,db file sequential read average_waits除以db file scattered readaverage_waits(Timed_statistics=true,否则average_waits0).

先看下生产系统E:

SQL> show parameter timed_statistics;

NAME TYPE

------------------------------------ ---------------------------------

VALUE

------------------------------

timed_statistics boolean

TRUE

SQL> select event,average_wait from v$system_event

2 where event like 'db file s%';

EVENT

--------------------------------------------------------------------------------

AVERAGE_WAIT

------------

db file sequential read

0

db file scattered read

0

db file single write

1

不巧,都是0。该系统并不是很繁忙。

那再看看生产系统A,平时CPU负载在60~90%,不过可惜也都是0。最后找下来我这里的系统没有一台不是0的。这个,似乎我们的SQL还是不错的,至少没有过多的IO耗费。

看来这个值的调校只有在

Eygle有一篇文章是讲optimizer_index_cost_adj与成本计算,那来按他的方式来找这个optimizer_index_cost_adj的临界值。

测试表的结构。

SQL> desc tst2_country;

Name Null? Type

----------------------------------------- -------- ----------------------------

COUNTRY_CO NOT NULL VARCHAR2(5)

COUNTRY_EN VARCHAR2(30)

COUNTRY_NA VARCHAR2(30)

EXAM_MARK VARCHAR2(1)

HIGH_LOW VARCHAR2(1)

测试表的资料数

SQL> select count(*) from tst2_country;

COUNT(*)

----------

245

Indexindx_tst2 tst2_country(country_co)

分析table

SQL> analyze table tst2_country compute statistics;

Table analyzed.

SQL> show parameter optimizer;

NAME TYPE

------------------------------------ ---------------------------------

VALUE

------------------------------

optimizer_dynamic_sampling integer

1

optimizer_features_enable string

9.2.0

optimizer_index_caching integer

0

optimizer_index_cost_adj integer

100

optimizer_max_permutations integer

NAME TYPE

------------------------------------ ---------------------------------

VALUE

------------------------------

2000

optimizer_mode string

CHOOSE

---------------------------------------------------------------------下面开始测试。

SQL> set autotrace traceonly;

SQL> select * from tst2_country where country_co=304;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=59)

1 0 TABLE ACCESS (FULL) OF 'TST2_COUNTRY' (Cost=2 Card=1 Bytes

=59)

Statistics

----------------------------------------------------------

0 recursive calls

0 db block gets

6 consistent gets

0 physical reads

0 redo size

841 bytes sent via SQL*Net to client

655 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> select /*+index(tst2_country indx_tst2)*/ * from tst2_country where country_co=304;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=59)

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TST2_COUNTRY' (Cost=2 Ca

rd=1 Bytes=59)

2 1 INDEX (FULL SCAN) OF 'INDX_TST2' (NON-UNIQUE) (Cost=1 Ca

rd=1)

Statistics

----------------------------------------------------------

0 recursive calls

0 db block gets

3 consistent gets

0 physical reads

0 redo size

841 bytes sent via SQL*Net to client

655 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

以上2笔,Index方式Consistent gets=3, FTS方式Consistent gets=6。从logic IO的角度看,INDEX方式应该更好一点。

cost看,2者的cost都是2。可能最终表达结果有精简过,实质上我理解:精简前的值FTS方式会更小点,所以CBO选择了FTS

下面是更改optimizer_index_cost_adj的测试:

设为50

SQL> alter session set optimizer_index_cost_adj=50;

Session altered.

SQL> show parameter optimizer_index;

NAME TYPE

------------------------------------ ---------------------------------

VALUE

------------------------------

optimizer_index_caching integer

0

optimizer_index_cost_adj integer

50

再来看走index的情况:

SQL> select /*+index(tst2_country indx_tst2)*/ * from tst2_country where country_co=304;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=59)

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TST2_COUNTRY' (Cost=1 Ca

rd=1 Bytes=59)

2 1 INDEX (FULL SCAN) OF 'INDX_TST2' (NON-UNIQUE) (Cost=1 Ca

rd=1)

Statistics

----------------------------------------------------------

0 recursive calls

0 db block gets

3 consistent gets

0 physical reads

0 redo size

841 bytes sent via SQL*Net to client

655 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

现在的cost变成1了。

再看不+hint的情况:

SQL> select * from tst2_country where country_co=304;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=59)

1 0 TABLE ACCESS (FULL) OF 'TST2_COUNTRY' (Cost=2 Card=1 Bytes

=59)

Statistics

----------------------------------------------------------

0 recursive calls

0 db block gets

6 consistent gets

1 physical reads

0 redo size

841 bytes sent via SQL*Net to client

655 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

FTSCost=2, 产生了physical reads, 我想是FTSblock比较容易被清出data buffer

没想到Oracle没选cost=1的方式。

下面清除data buffer shared_pool再看

SQL> alter system set events='immediate trace name flush_cache';

System altered.

SQL> alter system flush shared_pool;

System altered.

SQL> select * from tst2_country where country_co=304;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=59)

1 0 TABLE ACCESS (FULL) OF 'TST2_COUNTRY' (Cost=2 Card=1 Bytes

=59)

Statistics

----------------------------------------------------------

260 recursive calls

0 db block gets

43 consistent gets

12 physical reads

0 redo size

841 bytes sent via SQL*Net to client

655 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

4 sorts (memory)

0 sorts (disk)

1 rows processed

+hint的情况

SQL> alter system set events='immediate trace name flush_cache';

System altered.

SQL> alter system flush shared_pool;

System altered.

SQL> select /*+index(tst2_country indx_tst2)*/ * from tst2_country where country_co=304;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=59)

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TST2_COUNTRY' (Cost=1 Ca

rd=1 Bytes=59)

2 1 INDEX (FULL SCAN) OF 'INDX_TST2' (NON-UNIQUE) (Cost=1 Ca

rd=1)

Statistics

----------------------------------------------------------

260 recursive calls

0 db block gets

40 consistent gets

8 physical reads

0 redo size

841 bytes sent via SQL*Net to client

655 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

4 sorts (memory)

0 sorts (disk)

1 rows processed

依然走FTSOracle 竟然没有选cost比较小的PLAN.

本来是要测optimizer_index_cost_adj的选值的,没想到测出这个来。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10856805/viewspace-997021/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10856805/viewspace-997021/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值