ITPub博客

首页 > 数据库 > Oracle > optimizer_index_cost_adj的测试 I

optimizer_index_cost_adj的测试 I

原创 Oracle 作者:Karsus 时间:2008-01-10 09:18:09 0 删除 编辑

optimizer_index_cost_adj的测试。

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

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

[@more@]

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

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

生产环境是RHEL4up4+Oracle 9i.

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

先看下生产系统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

Index:indx_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

FTS。Cost=2, 产生了physical reads, 我想是FTS的block比较容易被清出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

依然走FTS。Oracle 竟然没有选cost比较小的PLAN.

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

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

请登录后发表评论 登录
全部评论
  • 博文量
    43
  • 访问量
    150218