现在环境
实验下INDEX FAST FULL SCAN 的计算
我们知道INDEX FAST FULL SCAN 是可以用db_file_multiblock_read_count 影响 采取scattered read的
SQL> show parameter db_file_m
NAME TYPE VALUE
------------------------------------ ----------- -----------------
db_file_multiblock_read_count integer 16
SQL> alter system set "_cache_stats_monitor"=false;
系统已更改。
SQL> alter system set "_optimizer_cache_stats"=false;
系统已更改。
SQL> alter system set "_optimizer_cost_model"=choose;
系统已更改。
以上是前面实验时候修改的参数,实际VALUE为 上面修改回来的值
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> select count(*) from t1;
COUNT(*)
----------
10000
SQL> create index t1_ind on t1(a);
SQL> set autotrace traceonly explain
SQL> alter session set events '10053 trace name context forever';
会话已更改。
SQL> select count(*) from t1;
执行计划
----------------------------------------------------------
Plan hash value: 3724264953
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 10000 | 6 (0)| 00:00:01 |
-------------------------------------------------------------------
SQL> select count(*) from t1 where a>6000;
执行计划
----------------------------------------------------------
Plan hash value: 2264155217
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX FAST FULL SCAN| T1_IND | 4000 | 12000 | 6 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("A">6000)
可以看到INDFFS COST 与FTS COST 一样(计算方式也应该一样)~~~~~~~~~~~~~~~~~~~~~~*****************************
****************
select count(*) from t1**********************************FTS时候
*********************
QUERY BLOCK SIGNATURE
*********************
qb name was generated
signature (optimizer): qb_name=SEL$1 nbfros=1 flg=0
fro(0): flg=0 bjn=52816 hint_alias="T1"@"SEL$1"
*****************************
SYSTEM STATISTICS INFORMATION
*****************************
Using NOWORKLOAD Stats
CPUSPEED: 1271 millions instruction/sec
IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
IOSEEKTIM: 10 milliseconds (default is 10)
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: T1 Alias: T1
#Rows: 10000 #Blks: 20 AvgRowLen: 3.00
Index Stats::
Index: T1_IND Col#: 1
LVLS: 1 #LB: 21 #DK: 10000 LB/K: 1.00 DB/K: 1.00 CLUF: 16.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: 6.11 Resp: 6.11 Degree: 0
Cost_io: 6.00 Cost_cpu: 1642429
Resp_io: 6.00 Resp_cpu: 1642429
Best:: AccessPath: TableScan
Cost: 6.11 Degree: 1 Resp: 6.11 Card: 10000.00 Bytes: 0
Final - All Rows Plan: Best join order: 1
Cost: 6.1077 Degree: 1 Card: 10000.0000 Bytes: 0
Resc: 6.1077 Resc_io: 6.0000 Resc_cpu: 1642429
Resp: 6.1077 Resp_io: 6.0000 Resc_cpu: 1642429
~~~~~~~~~~~~~~~~~~~
QUERY BLOCK TEXT
****************
select count(*) from t1 where a>6000*****************************index fast full scan 时
*********************
QUERY BLOCK SIGNATURE
*********************
qb name was generated
signature (optimizer): qb_name=SEL$1 nbfros=1 flg=0
fro(0): flg=0 bjn=52816 hint_alias="T1"@"SEL$1"
*****************************
SYSTEM STATISTICS INFORMATION
*****************************
Using NOWORKLOAD Stats
CPUSPEED: 1271 millions instruction/sec
IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
IOSEEKTIM: 10 milliseconds (default is 10)
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: T1 Alias: T1
#Rows: 10000 #Blks: 20 AvgRowLen: 3.00
Index Stats::
Index: T1_IND Col#: 1
LVLS: 1 #LB: 21 #DK: 10000 LB/K: 1.00 DB/K: 1.00 CLUF: 16.00
SINGLE TABLE ACCESS PATH
Column (#1): A(NUMBER)
AvgLen: 4.00 NDV: 10000 Nulls: 0 Density: 1.0000e-004 Min: 1 Max: 10000
Table: T1 Alias: T1
Card: Original: 10000 Rounded: 4000 Computed: 4000.40 Non Adjusted: 4000.40
Access Path: TableScan~~~~~~~~~~~~~可以看到 表SCAN 时候成本
Cost: 6.14 Resp: 6.14 Degree: 0
Cost_io: 6.00 Cost_cpu: 2142429
Resp_io: 6.00 Resp_cpu: 2142429
Access Path: index (index (FFS))~~~~~~~~~~~~采用INDX时候路径 成本 比FTS 成本小 6.12<6.14 所以OPTIMIZER 选择INDEX FAST FULL SACN
Index: T1_IND
resc_io: 6.00 resc_cpu: 1849550
ix_sel: 0.0000e+000 ix_sel_with_filters: 1
Access Path: index (FFS)
Cost: 6.12 Resp: 6.12 Degree: 1
Cost_io: 6.00 Cost_cpu: 1849550
Resp_io: 6.00 Resp_cpu: 1849550
Access Path: index (IndexOnly)
Index: T1_IND
resc_io: 10.00 resc_cpu: 871414
ix_sel: 0.40004 ix_sel_with_filters: 0.40004
Cost: 10.06 Resp: 10.06 Degree: 1
Best:: AccessPath: IndexFFS Index: T1_IND~~~~~~~~~~~~~~~~~~~~~~~~~OPTIMIZER最后选择了最好的执行方式INDEX FFS
Cost: 6.12 Degree: 1 Resp: 6.12 Card: 4000.40 Bytes: 0
***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***************************************
Considering cardinality-based initial join order.
***********************
Join order[1]: T1[T1]#0
***********************
Best so far: Table#: 0 cost: 6.1213 card: 4000.4000 bytes: 12000
(newjo-stop-1) k:0, spcnt:0, perm:1, maxperm:80000
*********************************
Number of join permutations tried: 1
*********************************
Final - All Rows Plan: Best join order: 1
Cost: 6.1213 Degree: 1 Card: 4000.0000 Bytes: 12000
Resc: 6.1213 Resc_io: 6.0000 Resc_cpu: 1849550
Resp: 6.1213 Resp_io: 6.0000 Resc_cpu: 1849550
*********可以看到此例中FTS IO COST 与INDEX FAST FULL SCAN IO COST 部分是一样的CPU COST(计算方式应该一样),要比 FTS时候CPU COST小些
SQL> select leaf_blocks from dba_indexes where index_name='T1_IND';
LEAF_BLOCKS
-----------
21 ~~~~~~~~~~~~~~~~~应该是用LEAF BLOCK 代入公式计算的~~~~~~~~~(USED LEAF BLOCK)
Cost = (
#SRds +
#MRds * mreadtim / sreadtim +**************io cost
#CPUCycles / (cpuspeed * sreadtim)********cpu cost
计算*使用 默认信息**************************
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
SQL> select leaf_blocks from dba_indexes where index_name='T1_IND';
LEAF_BLOCKS
-----------
21
SQL> select pname,pval1 from aux_stats$ where sname='SYSSTATS_MAIN';
PNAME PVAL1
------------------------------ ----------
CPUSPEED
CPUSPEEDNW 1270.63969
IOSEEKTIM 10
IOTFRSPEED 4096
MAXTHR
MBRC
MREADTIM
SLAVETHR
SREADTIM
SQL> select ceil((21/16)*(42/12)) from dual;
CEIL((21/16)*(42/12))
---------------------
5
又由于 _table_scan_cost_plus_one = true 加1 所以IO COST=6
***********************************
SQL> create table t2 (a int ,b char(2000),c char(2000));
表已创建。
SQL> declare
2 begin
3 for i in 1..100 loop
4 insert into t2 values(i,'a','a');
5 end loop;
6 commit;
7 end;
8 /
PL/SQL 过程已成功完成。
SQL> execute dbms_stats.gather_table_stats('SYS','T2');
PL/SQL 过程已成功完成。
SQL> select blocks from user_tables where table_name='T2';
BLOCKS
----------
100
SQL> create index t2_ind on t2(a);
索引已创建。
SQL> select leaf_blocks from dba_indexes where index_name='T2_IND';
LEAF_BLOCKS
-----------
1
SQL> execute dbms_stats.gather_index_stats('SYS','T2_IND');
PL/SQL 过程已成功完成。
SQL> select leaf_blocks from dba_indexes where index_name='T2_IND';
LEAF_BLOCKS
-----------
1
SQL> set autotrace traceonly explain
SQL> alter session set events '10053 trace name context forever';
会话已更改。
SQL> select a from t2;
执行计划
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 300 | 24 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T2 | 100 | 300 | 24 (0)| 00:00:01 |
--------------------------------------------------------------------------
SQL> select a from t2 where a>60;
执行计划
----------------------------------------------------------
Plan hash value: 2876512201
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 40 | 120 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T2_IND | 40 | 120 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A">60)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
可以看到OPTIMIZER 并没有使用INDEXFFS~~~原因很简单 INDEX RANGE SCAN COST更低
但从10053中TRACE中可以看出OPTIMIZER 做出了INDEXFFS的COST 并做了对比
Table Stats::
Table: T2 Alias: T2
#Rows: 100 #Blks: 100 AvgRowLen: 4005.00
Index Stats::
Index: T2_IND Col#: 1
LVLS: 0 #LB: 1 #DK: 100 LB/K: 1.00 DB/K: 1.00 CLUF: 100.00
***************************************
SINGLE TABLE ACCESS PATH
Column (#1): A(NUMBER)
AvgLen: 3.00 NDV: 100 Nulls: 0 Density: 0.01 Min: 1 Max: 100
Table: T2 Alias: T2
Card: Original: 100 Rounded: 40 Computed: 40.40 Non Adjusted: 40.40
Access Path: TableScan
Cost: 24.05 Resp: 24.05 Degree: 0~~~~~~~~~~~~~FTS时候COST
Cost_io: 24.00 Cost_cpu: 732144
Resp_io: 24.00 Resp_cpu: 732144
Access Path: index (index (FFS))
Index: T2_IND
resc_io: 2.00 resc_cpu: 24121
ix_sel: 0.0000e+000 ix_sel_with_filters: 1
Access Path: index (FFS)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~INDEX FFS时候COST
Cost: 2.00 Resp: 2.00 Degree: 1
Cost_io: 2.00 Cost_cpu: 24121
Resp_io: 2.00 Resp_cpu: 24121
Access Path: index (IndexOnly)~~~~~~~~~~~~~~~~~~~INDEX RANGE SCAN时COST(INDEX COST计算会在后面实验于FTS公式不一样)
Index: T2_IND
resc_io: 1.00 resc_cpu: 15321
ix_sel: 0.40404 ix_sel_with_filters: 0.40404
Cost: 1.00 Resp: 1.00 Degree: 1
Best:: AccessPath: IndexRange Index: T2_IND
Cost: 1.00 Degree: 1 Resp: 1.00 Card: 40.40 Bytes: 0
因为INDEX FFSCOST Cost_io: 2.00
按照公式来算
Cost = (
#SRds +
#MRds * mreadtim / sreadtim +**************io cost
#CPUCycles / (cpuspeed * sreadtim)********cpu cost
计算*使用 默认信息**************************
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
SQL> select pname,pval1 from aux_stats$ where sname='SYSSTATS_MAIN';
PNAME PVAL1
------------------------------ ----------
CPUSPEED
CPUSPEEDNW 1270.63969
IOSEEKTIM 10
IOTFRSPEED 4096
MAXTHR
MBRC
MREADTIM
SLAVETHR
SREADTIM
SQL> select ceil((1/16)*(42/12)) from dual;
CEIL((1/16)*(42/12))
--------------------
1
_table_scan_cost_plus_one = true 加1 所以IO COST=2
SQL> alter system set "_table_scan_cost_plus_one"=false;~~~去掉加一
系统已更改。
SQL> set autotrace traceonly explain
SQL> alter session set events '10053 trace name context forever';
会话已更改。
SQL> select a from t2 where a>60;
执行计划
----------------------------------------------------------
Plan hash value: 2876512201
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 40 | 120 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T2_IND | 40 | 120 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A">60)
SINGLE TABLE ACCESS PATH
Column (#1): A(NUMBER)
AvgLen: 3.00 NDV: 100 Nulls: 0 Density: 0.01 Min: 1 Max: 100
Table: T2 Alias: T2
Card: Original: 100 Rounded: 40 Computed: 40.40 Non Adjusted: 40.40
Access Path: TableScan
Cost: 23.05 Resp: 23.05 Degree: 0
Cost_io: 23.00 Cost_cpu: 732144
Resp_io: 23.00 Resp_cpu: 732144
Access Path: index (index (FFS))
Index: T2_IND
resc_io: 1.00 resc_cpu: 24121
ix_sel: 0.0000e+000 ix_sel_with_filters: 1
Access Path: index (FFS)
Cost: 1.00 Resp: 1.00 Degree: 1~~~~~~~~~~~~~~~~~~~~~~可以看 到IOCOST 部分已经为1 但是CPU 部分比 INDEX RANGSCAN 要高
Cost_io: 1.00 Cost_cpu: 24121
Resp_io: 1.00 Resp_cpu: 24121
Access Path: index (IndexOnly)
Index: T2_IND
resc_io: 1.00 resc_cpu: 15321~~~~~~~~~~~~~~~这CPU 部分 COST小,所以ORACLE 还是选择了INDEX RANG SCAN
ix_sel: 0.40404 ix_sel_with_filters: 0.40404
Cost: 1.00 Resp: 1.00 Degree: 1
Best:: AccessPath: IndexRange Index: T2_IND
Cost: 1.00 Degree: 1 Resp: 1.00 Card: 40.40 Bytes: 0
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12020513/viewspace-613946/ ,如需转载,请注明出处,否则将追究法律责任。