行预取是指当需要从同一个数据块中读取多行时,Oracle数据库引擎只通过一次逻辑读就可以同时获取多行数据,以提高性能。一次行预取读取的行数由arraysize指定。
聚簇因子表明索引中多少相邻的索引键值 不指向表中相同的数据块,简单来说,聚簇因子高(即接近于表行数),表示索引键值顺序和行在数据块中的存储顺序很不一样,行预取的作用就不明显;聚簇因子低(即接近于表数据块个数),表示索引键值顺序和行在数据块中的存储顺序很相似,行预取的作用就很明显。
下面做个简单的实验:
--创建一个包含主键的测试表:
SQL>create table t (
2 id number,
3 pad varchar2(4000),
4 constraint t_pk primary key (id)
5 );
--以id升序的顺序插入1000行数据:
SQL>insert into t
2 select rownum as id, dbms_random.string('p',500) as pad
3 from dual
4 connect by level <= 1000;
--查看表占用了多少数据块:
SQL>analyze table T compute statistics;
SQL>select blocks,num_rows from user_tables where table_name='T';
BLOCKS NUM_ROWS
---------- ----------
73 1000
--查看索引的聚簇因子:
SQL>select clustering_factor from user_indexes where index_name='T_PK';
CLUSTERING_FACTOR
-----------------
72
可以发现聚簇因子和表的数据块个数相近,说明聚簇因子很低,这种情况非常理想,行预取作用明显,可以有效地降低全索引扫描的逻辑读:
SQL>set autotrace traceonly
SQL>select /*+ index(t t_pk) */ * from t;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=75 Card=1000 Bytes=503000)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE) (Cost=75 Card =1000 Bytes=503000)
2 1 INDEX (FULL SCAN) OF 'T_PK' (INDEX (UNIQUE)) (Cost=3 Card=1000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
205 consistent gets
0 physical reads
0 redo size
512484 bytes sent via SQL*Net to client
741 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed
--以id无序的顺序插入
SQL>truncate table t;
SQL>insert into t
2 select rownum as id, dbms_random.string('p',500) as pad
3 from dual
4 connect by level <=1000 order by dbms_random.value;
--查看表占用了多少数据块:
SQL>analyze table T compute statistics;
SQL>select blocks,num_rows from user_tables where table_name='T';
BLOCKS NUM_ROWS
---------- ----------
73 1000
--查看索引的聚簇因子:
SQL>select clustering_factor from user_indexes where index_name='T_PK';
CLUSTERING_FACTOR
-----------------
986
可以发现聚簇因子和表的数据行数相近,说明聚簇因子很高,这种情况很不理想,行预取几乎无法发挥作用,逻辑读很高:
SQL>set autotrace traceonly
SQL>select /*+ index(t t_pk) */ * from t;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=990 Card=1000 Bytes=503000)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE) (Cost=990 Card=1000 Bytes=503000)
2 1 INDEX (FULL SCAN) OF 'T_PK' (INDEX (UNIQUE)) (Cost=3 Card=1000)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
1056 consistent gets
0 physical reads
0 redo size
512482 bytes sent via SQL*Net to client
741 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed
====================================
2012-02-07 补充:
其实可以这么理解聚簇因子:索引键值是有序的,而表却不一定是有序的,聚簇因子用来度量表的有序程度,聚簇因子越低(越接近于数据块个数),表示表的有序程度越高;聚簇因子越高(越接近于表行数),表示表的有序程度越低。
聚簇因子表明索引中多少相邻的索引键值 不指向表中相同的数据块,简单来说,聚簇因子高(即接近于表行数),表示索引键值顺序和行在数据块中的存储顺序很不一样,行预取的作用就不明显;聚簇因子低(即接近于表数据块个数),表示索引键值顺序和行在数据块中的存储顺序很相似,行预取的作用就很明显。
下面做个简单的实验:
--创建一个包含主键的测试表:
SQL>create table t (
2 id number,
3 pad varchar2(4000),
4 constraint t_pk primary key (id)
5 );
--以id升序的顺序插入1000行数据:
SQL>insert into t
2 select rownum as id, dbms_random.string('p',500) as pad
3 from dual
4 connect by level <= 1000;
--查看表占用了多少数据块:
SQL>analyze table T compute statistics;
SQL>select blocks,num_rows from user_tables where table_name='T';
BLOCKS NUM_ROWS
---------- ----------
73 1000
--查看索引的聚簇因子:
SQL>select clustering_factor from user_indexes where index_name='T_PK';
CLUSTERING_FACTOR
-----------------
72
可以发现聚簇因子和表的数据块个数相近,说明聚簇因子很低,这种情况非常理想,行预取作用明显,可以有效地降低全索引扫描的逻辑读:
SQL>set autotrace traceonly
SQL>select /*+ index(t t_pk) */ * from t;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=75 Card=1000 Bytes=503000)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE) (Cost=75 Card =1000 Bytes=503000)
2 1 INDEX (FULL SCAN) OF 'T_PK' (INDEX (UNIQUE)) (Cost=3 Card=1000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
205 consistent gets
0 physical reads
0 redo size
512484 bytes sent via SQL*Net to client
741 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed
--以id无序的顺序插入
SQL>truncate table t;
SQL>insert into t
2 select rownum as id, dbms_random.string('p',500) as pad
3 from dual
4 connect by level <=1000 order by dbms_random.value;
--查看表占用了多少数据块:
SQL>analyze table T compute statistics;
SQL>select blocks,num_rows from user_tables where table_name='T';
BLOCKS NUM_ROWS
---------- ----------
73 1000
--查看索引的聚簇因子:
SQL>select clustering_factor from user_indexes where index_name='T_PK';
CLUSTERING_FACTOR
-----------------
986
可以发现聚簇因子和表的数据行数相近,说明聚簇因子很高,这种情况很不理想,行预取几乎无法发挥作用,逻辑读很高:
SQL>set autotrace traceonly
SQL>select /*+ index(t t_pk) */ * from t;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=990 Card=1000 Bytes=503000)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE) (Cost=990 Card=1000 Bytes=503000)
2 1 INDEX (FULL SCAN) OF 'T_PK' (INDEX (UNIQUE)) (Cost=3 Card=1000)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
1056 consistent gets
0 physical reads
0 redo size
512482 bytes sent via SQL*Net to client
741 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed
====================================
2012-02-07 补充:
其实可以这么理解聚簇因子:索引键值是有序的,而表却不一定是有序的,聚簇因子用来度量表的有序程度,聚簇因子越低(越接近于数据块个数),表示表的有序程度越高;聚簇因子越高(越接近于表行数),表示表的有序程度越低。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26277071/viewspace-715081/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/26277071/viewspace-715081/