ITPub博客

首页 > Linux操作系统 > Linux操作系统 > oracle实验记录 (全表扫描COST计算方法)

oracle实验记录 (全表扫描COST计算方法)

原创 Linux操作系统 作者:fufuh2o 时间:2009-08-31 13:04:40 0 删除 编辑



实验下FTS 时候 COST 的计算

 


公式:    
According to the CPU costing model:
Cost = (
#SRds * sreadtim +
#MRds * mreadtim +~~~~~~~~~~~~~~~~~~~~~~~~~~~~来自于cost-based oracle书中
#CPUCycles / cpuspeed
) / sreadtim
where
#SRDs - number of single block reads
#MRDs - number of multi block reads
#CPUCycles - number of CPU Cycles
sreadtim - single block read time
mreadtim - multi block read time
cpuspeed - CPU cycles per second


COST=CPU COST+IO COST (8I 不计算CPU COST)
SQL> select * from v$version;实验版本

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

测试
SQL> create table t1 (a int);

表已创建。

 

SQL> ed
已写入 file afiedt.buf

  1  declare
  2  begin
  3  for i in 1..10000 loop
  4  insert into t1 values(i);
  5  end loop;
  6* end;
SQL> /

PL/SQL 过程已成功完成。

SQL> select blocks from user_tables where table_name='T1';

    BLOCKS
----------


SQL> exec dbms_stats.gather_table_stats('SYS','T1');

PL/SQL 过程已成功完成。

SQL> select blocks from user_tables where table_name='T1';

    BLOCKS
----------
        20

SQL> show parameter db_block_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_block_size                        integer     8192
SQL> show parameter db_file_mu

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count        integer     16


SQL> alter session set "_optimizer_cost_model"=CPU;

会话已更改。

 

SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     6   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------


统计信息
----------------------------------------------------------
        135  recursive calls
          0  db block gets
        703  consistent gets
          0  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)

 


SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';~~~查看CBO计划

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     6   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        690  consistent gets
          0  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed
SINGLE TABLE ACCESS PATH
  Table: T1  Alias: T1    
    Card: Original: 10000  Rounded: 10000  Computed: 10000.00  Non Adjusted: 10000.00
  Access Path: TableScan
    Cost:  6.28  Resp: 6.28  Degree: 0
      Cost_io: 6.00  Cost_cpu: 1642429~~~~~~~~~~~~~~~~~~~~~~IO部分cost=6
      Resp_io: 6.00  Resp_cpu: 1642429
  Best:: AccessPath: TableScan
         Cost: 6.28  Degree: 1  Resp: 6.28  Card: 10000.00  Bytes: 0

**********Cost_io: 6.00  IO 部分  ,CPU=0.28
SQL> select pname,pval1 from aux_stats$ where sname='SYSSTATS_MAIN';

PNAME                               PVAL1
------------------------------ ----------
CPUSPEED
CPUSPEEDNW                     484.974958  speed in millions of operations per second
IOSEEKTIM                              10  disk seek time in milliseconds
IOTFRSPEED                           4096   disk transfer time in bytes per millisecond
MAXTHR
MBRC
MREADTIM
SLAVETHR
SREADTIM

已选择9行。以上没有信息收集 ORACLE 会用DEFAULT 计算************

计算*使用 默认信息**************************
MBRC=db_file_multiblock_read_count=16
sreadtim=IOSEEKTIM+db+block_size/IOTFRSPEED=12
mreadtime=IOSEEKTIM+db_file_multiblock_read_count*db+block_size/IOTFRSPEED=42

MDRS=BLOCKS/MBRC
#SRds =0(single-block reads),因为是 FTS 都是多块读取
最早的公式变换一下(除开)
Cost = (
#SRds +
#MRds * mreadtim / sreadtim +**************io cost
#CPUCycles / (cpuspeed * sreadtim)********cpu cost

SQL> select 20/16*42/12 from dual;

20/16*42/12
-----------
      4.375

4.375=5 由于
_optimizer_ceil_cost           TRUE                      TRUE      FALSE      FALSE

CEIL cost in CBO~~~~~~~~~~取整

SQL> select ceil(20/16*42/12) from dual;

CEIL(20/16*42/12)
-----------------
                5~~~~~~~~~~~~~~~~~~~~~~~~~~~IO 部分IO COST

又由于 _table_scan_cost_plus_one           = true   加1 所以IO COST=6
true时候COST+1 表示开始需要访问表的SEGMENT HEADER BLOCK,这是优化器的内置技巧之一(避免小表中用INDEX)
********oracle cost-based oracle原文描述 _table_scan_cost_plus_one
This is the type of minor tweak that appears surprisingly frequently in Oracle, and makes
it very difficult to produce any sort of documentation about the optimizer that is both concise
and complete. In this case, the change may represent the requirement for the necessary access
to the table’s segment header block at the start of a tablescan; alternatively it may simply be
one of several tricks built into the optimizer to bias it towards using indexed access paths on
very small tables.
***********
CPU 部分 转换成IO COST 单位

#CPUCycles / (cpuspeed * sreadtim)
#CPUCycles:1642429
cpuspeed default 使用 CPUSPEEDNW
sreadtime:12(milliseconds)=12000(microseconds)
 
SQL> select 1642429/(484*12000) from dual;

1642429/(484*12000)
-------------------
         .282787362

 

 

*********************
实验改_table_scan_cost_plus_on为FALSE
SQL> alter system set "_table_scan_cost_plus_one"=false;

系统已更改。

 

SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     5   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     5   (0)| 00:00:01 |
--------------------------------------------------------------------------


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        690  consistent gets
          0  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

 


trace中
  _table_scan_cost_plus_one           = false

Table Stats::
  Table: T1  Alias: T1
    #Rows: 10000  #Blks:  20  AvgRowLen:  3.00
***************************************
SINGLE TABLE ACCESS PATH
  Table: T1  Alias: T1    
    Card: Original: 10000  Rounded: 10000  Computed: 10000.00  Non Adjusted: 10000.00
  Access Path: TableScan
    Cost:  5.28  Resp: 5.28  Degree: 0
      Cost_io: 5.00  Cost_cpu: 1642429
      Resp_io: 5.00  Resp_cpu: 1642429
  Best:: AccessPath: TableScan
         Cost: 5.28  Degree: 1  Resp: 5.28  Card: 10000.00  Bytes: 0

可以看出 IO COST=5   CPU=0.28

 


*************************
SQL> alter system set "_optimizer_ceil_cost"=false;

发现改过这个参数后 oracle 会出现些混乱

系统已更改。
NAME                           VALUE                     ISDEFAULT ISMOD      ISADJ

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

KSPPDESC
-----------------------------------------------------------------------------------
-------------------------------------------------
_optimizer_ceil_cost           FALSE                     FALSE     FALSE      FALSE

CEIL cost in CBO


SQL> /
输入 par 的值:  table_scan_cost_plus_one
原值   14:   x.ksppinm like '%_&par%'
新值   14:   x.ksppinm like '%_table_scan_cost_plus_one%'

NAME                           VALUE                     ISDEFAULT ISMOD      ISADJ

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

KSPPDESC
-----------------------------------------------------------------------------------
-------------------------------------------------
_table_scan_cost_plus_one      FALSE                     FALSE     FALSE      FALSE

bump estimated full table scan and index ffs cost by one

 

SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     6  (17)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     6  (17)| 00:00:01 |
--------------------------------------------------------------------------


统计信息
----------------------------------------------------------
        154  recursive calls
          0  db block gets
        706  consistent gets
         23  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
      10000  rows processed

SQL> exit


_table_scan_cost_plus_one           = false

 

Table Stats::
  Table: T1  Alias: T1
    #Rows: 10000  #Blks:  20  AvgRowLen:  3.00
***************************************
SINGLE TABLE ACCESS PATH
  Table: T1  Alias: T1    
    Card: Original: 10000  Rounded: 10000  Computed: 10000.00  Non Adjusted: 10000.00
  Access Path: TableScan
    Cost:  5.28  Resp: 5.28  Degree: 0
      Cost_io: 5.00  Cost_cpu: 1642429
      Resp_io: 5.00  Resp_cpu: 1642429
  Best:: AccessPath: TableScan
         Cost: 6.00  Degree: 1  Resp: 5.28  Card: 10000.00  Bytes: 0          注意cost  Cost: 6.00  Degree: 1(并行度)  Resp: 5.28(Cost for full parallel   execution of a step.) 这个是指并行时候的COST ,现在并行度为1 就代表串 行 ,oracle向上取整COST 到了 6(将总5.28) 原来是5.28 autotrace中 显示为5 现在为6

理应 为4才对 不取整 不加一 IO COST应该等于4 ,而实验结果有点奇怪


SQL> alter system set "_optimizer_ceil_cost"=true;(这个参数只在CBO COST计算时 使用CPU_costing时候 才有用)

系统已更改。
SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     5   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     5   (0)| 00:00:01 |
--------------------------------------------------------------------------


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        690  consistent gets
          0  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

SQL> alter session set events '10053 trace name context off';               改回后正常了

 

 


会话已更改。


****************************模拟下oracle 8i         传统COST计算 (只计算IO部分)

SQL> alter system set "_table_scan_cost_plus_one"=true;

系统已更改。


SQL> alter system set "_optimizer_cost_model"=io~~~~~~~~~~~~~换成传统IO成本计算~~这将只单一的结算IO COST 并且不使用系统统计信息
  2  ;

系统已更改。

SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

----------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost  |
----------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     4 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     4 |
----------------------------------------------------------

Note
-----
   - cpu costing is off (consider enabling it)


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        690  consistent gets
          0  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

SQL> alter session set events '10053 trace name context off';

会话已更改。

TRACE中
  _optimizer_cost_model               = io
Table Stats::
  Table: T1  Alias: T1
    #Rows: 10000  #Blks:  20  AvgRowLen:  3.00
***************************************
SINGLE TABLE ACCESS PATH
  Table: T1  Alias: T1    
    Card: Original: 10000  Rounded: 10000  Computed: 10000.00  Non Adjusted: 10000.00
  Access Path: TableScan
    Cost:  4.00  Resp: 4.00  Degree: 0
      Cost_io: 4.00  Cost_cpu: 0
      Resp_io: 4.00  Resp_cpu: 0
  Best:: AccessPath: TableScan
         Cost: 4.00  Degree: 1  Resp: 4.00  Card: 10000.00  Bytes: 0


这个4  COST=(HWM下block/adjusted dbf_mbrc)得出

ADJUSTER_MBRC=blocs/cost=20/4=5(大约 应该反复测试) 一般就是这么推出的(9I 和10G 不一样 )


db_file_multiblock_read_count Cost Adjusted dbf_mbrc(这个表来自COST-BASED ORACLE)9I条件下
4    2,396       4.17
8     1,518   6.59
16    962    10.40
32    610     16.39
64    387     25.84
128   245    40.82

与db_file_multiblock_read_count 大小有关系


Block Size Cost of 10,000 Block Scans Adjusted dbf_mbrc Cost for 80MB Scan(这个表来自COST-BASED ORACLE)9I条件下
2KB 611 16.39 2,439
4KB 963 10.40 1,925
8KB 1,519 6.59 1,519
8KB ASSM 1,540 n/a 1,540
16KB 2,397 4.17 1,199

块大小的影响

SQL> create table t2 (a int);

表已创建。


SQL> ed
已写入 file afiedt.buf

  1  declare
  2  begin
  3  for i in 1..5000 loop
  4  insert into t2 values(i);
  5  end loop;
  6* end;
SQL> /

PL/SQL 过程已成功完成。

SQL> commit;

提交完成。

SQL> exec dbms_stats.gather_table_stats('SYS','T2');

PL/SQL 过程已成功完成。

SQL> select blocks from user_tables where table_name='T2';

    BLOCKS
----------
        12

SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t2;

已选择5000行。


执行计划
----------------------------------------------------------
Plan hash value: 1513984157

----------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost  |
----------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  5000 | 15000 |     3 |
|   1 |  TABLE ACCESS FULL| T2   |  5000 | 15000 |     3 |
----------------------------------------------------------

Note
-----
   - cpu costing is off (consider enabling it)~~~~~~~关闭


统计信息
----------------------------------------------------------
        135  recursive calls
          0  db block gets
        362  consistent gets
          0  physical reads
          0  redo size
      88572  bytes sent via SQL*Net to client
       4048  bytes received via SQL*Net from client
        335  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
       5000  rows processed
SQL> select ceil(12/5)from dual;

CEIL(12/5)
----------
         3
            
TRACE中结果
_optimizer_cost_model               = io

 

SINGLE TABLE ACCESS PATH
  Table: T2  Alias: T2    
    Card: Original: 5000  Rounded: 5000  Computed: 5000.00  Non Adjusted: 5000.00
  Access Path: TableScan
    Cost:  3.00  Resp: 3.00  Degree: 0
      Cost_io: 3.00  Cost_cpu: 0
      Resp_io: 3.00  Resp_cpu: 0
  Best:: AccessPath: TableScan
         Cost: 3.00  Degree: 1  Resp: 3.00  Card: 5000.00  Bytes: 0

 

 

 

**********************关于 收集系统统计
SQL> alter system set "_optimizer_cost_model"=choose
  2  ;

系统已更改。
SQL> exec dbms_stats.gather_system_stats('START');

PL/SQL 过程已成功完成。

SQL> select count(*) from t1;

  COUNT(*)
----------
     10000

SQL> select count(*) from t2;

  COUNT(*)
----------
      5000

SQL> select count(*) from dba_users;

  COUNT(*)
----------
        28

SQL> select count(*) from dba_tables;

  COUNT(*)
----------
      1582

SQL> exec dbms_stats.gather_system_stats('STop');~~~~~~~~~~~~~~~~运行一阵收集信息

PL/SQL 过程已成功完成。
SQL> /

PNAME                               PVAL1
------------------------------ ----------
CPUSPEED                              743
CPUSPEEDNW                     484.974958
IOSEEKTIM                              10
IOTFRSPEED                           4096
MAXTHR                               2048
MBRC                                    4
MREADTIM                            6.364
SLAVETHR
SREADTIM                            5.769

已选择9行。

SQL> set autotrace traceonly
SQL> alter session set events '10053 trace name context forever';

会话已更改。

SQL> select * from t1;

已选择10000行。


执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 30000 |     7   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T1   | 10000 | 30000 |     7   (0)| 00:00:01 |
--------------------------------------------------------------------------


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        690  consistent gets
          0  physical reads
          0  redo size
     176812  bytes sent via SQL*Net to client
       7711  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

 

Cost = (
#SRds +
#MRds * mreadtim / sreadtim +**************io cost
#CPUCycles / (cpuspeed * sreadtim)********cpu cost


COST=20/4*6.364/5.796

SQL> select ceil(20/4*6.364/5.769) from dual;

CEIL(20/4*6.364/5.769)
----------------------
                     6
另外 table _table_scan_cost_plus_one 为TRUCE 所以 IO COST =7
TRACE中
_table_scan_cost_plus_one           = true
SYSTEM STATISTICS INFORMATION
*****************************
  Using WORKLOAD Stats
  CPUSPEED: 743 millions instructions/sec
  SREADTIM: 6 milliseconds
  MREADTIM: 6 millisecons
  MBRC: 4.000000 blocks
  MAXTHR: 2048 bytes/sec
  SLAVETHR: -1 bytes/sec
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
  Table: T1  Alias: T1
    #Rows: 10000  #Blks:  20  AvgRowLen:  3.00
***************************************
SINGLE TABLE ACCESS PATH
  Table: T1  Alias: T1    
    Card: Original: 10000  Rounded: 10000  Computed: 10000.00  Non Adjusted: 10000.00
  Access Path: TableScan
    Cost:  7.38  Resp: 7.38  Degree: 0
      Cost_io: 7.00  Cost_cpu: 1642429
      Resp_io: 7.00  Resp_cpu: 1642429
  Best:: AccessPath: TableScan
         Cost: 7.38  Degree: 1  Resp: 7.38  Card: 10000.00  Bytes: 0

这是采用收集系统统计信息之后COST 有所上升


cpu部分计算=1642429/(743*5769)=0.38   将CPU_COST 换算成IO 单位
? CPUSPEED = 743MHZ
? sreadtim = 5769 milliseconds = 5769 microseconds (standardizing units of time)
? #CPUCycles (called cpu_cost in the plan_table) = 1642429
#CPUCycles / (cpuspeed * sreadtim)
SQL> select 1642429/(743*5769) from dual;

1642429/(743*5769)
------------------
        .383175076

另外可以自己设置系统统计信息
delete aux_stats$
execute
dbms_stats.set_system_stats('CPUSPEED',500);
dbms_stats.set_system_stats('SREADTIM',5.0);
dbms_stats.set_system_stats('MREADTIM',30.0);
dbms_stats.set_system_stats('MBRC',12);


小结:oracle 10g _optimizer_cost_model CHOOSE模式 基本就是使用CPU_COSTING计算,所以需要系统统计信息 没有时候用DEFALUT的,不再用8I 那样传统的COST计算(只简单的计

算IO)

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

请登录后发表评论 登录
全部评论

注册时间:2009-06-26

  • 博文量
    182
  • 访问量
    426851