QUOTE:
最初由 Yong Huang 发布
I believe grassbell's test and Tom Kyte's same test show that fetching from buffer cache is indeed controlled by sqlplus array_size (among other things). Consistent gets is a concept related to buffer cache access, not PGA access. Actually I can't think of a way to count the number of times a server process reads from its own PGA.
Unduly small array size in sqlplus (or similar settings in other client environments) causes unnecessary block logical reads. I think asktom's site or his Expert One on One has quite a number of notes on this.
Yong Huang
我想说明的是,sarraysize 是影响了 process 去buffer cache 中搜集的记录,但实际上影响的应该是 进程一次去搜索的 buffer 的数量,并不是说,如果 arraysize 为1, 一个buffer有5条记录就要重复读这个buffer5次
tom 的书或者站点我很早前都读过了,就 process 去 buffer 中搜集数据这个问题,我问过 tom,他说 游标单条 fetch 的时候并不是说只fetch 一条记录(oci中有一个 prefetch呢),而是把 少量(也许是2,一个preread,也许是其他数字)的block 中一次性都搜集到 pga 中了
看看我的测试
SQL> show parameters block_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192
SQL> create table t(a char(2000));
Table created.
SQL> insert into t select 'a' from dba_objects where rownum < 101;
100 rows created.
插入100条记录,一个 block是装3条记录,也就是大约有34个block装数据
SQL> set arraysize 200
SQL> select * from t;
100 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'T'
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
39 consistent gets
0 physical reads
0 redo size
2901 bytes sent via SQL*Net to client
499 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed
这是正常的合理的结果
如果设置 arraysize 为1 ,按照楼主的猜想,那 逻辑读应该是超过 100 了,因为每个block要读 3次
那我们来看看
SQL> set arraysize 1
SQL> select * from t;
100 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'T'
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
71 consistent gets
0 physical reads
0 redo size
8830 bytes sent via SQL*Net to client
918 bytes received via SQL*Net from client
51 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed
很显然,一个 block 并没有被重复地读多次
至于100条记录却只有 51 SQL*Net roundtrips to/from client
这个应该是 OCI prefetch 的缘故
也就是说,arraysize 是控制了 process 一次返回给 client 的记录数,也可以认为是一次fetch搜集的记录数,但这个搜集过程是复杂的,并不是简单地说去 buffer cache 中一次只读 arraysize 这么多条记录,PGA 应该是参与了缓冲的
这个问题最先是 tom 含糊地告诉了我一句就没有深入了,当然,说 arraysize 影响了 logical reads 是没有错的,只不过这个logical reads 并不是简单地对 buffer cache 进行 reads ,里面存在 preread 到 PGA 和在 pga 中进行读的问题
我以前曾经做过实验来期望证明类似的一个观点,但是实验现象违背了猜想就去问tom,他是告诉我读实际上是 buffer cache ---> PGA (这是一个preread or cache 的作用,直接导致我当时的实验失败) ---- > clinet
我也忘记具体的实验了,大体是在一个游标中对少量记录的循环读取,读一条记录sleep 30秒,在另一个session中同时也对这些记录进行处理,结果发现该循环没有受到那个session的影响 ,而preread的解释则说明了这个现象