通常情况下数据库引擎每访问一个数据块将产生至少一个逻辑读。而行预取与逻辑读息息相关。行预取是指当客户端从数据库获取数据时
可以采用单行也可以采用多行方式返回数据。当采用多行方式时,则会预取多条记录存储在客户端内存中以避免后续多次该数据的请求所致的
各种开销(LIO,PIO,NET IO)。一般预取行数越大,则所产生的开销越小,当达到临界值时其变化不大。
一、演示
二、分析
假定使用select * from t发布查询,此时表上每个数据块为16行,且arraysize 的设置为15(缺省值),
则
第一次fetch, 读第一块15行,此时产生第1次consistent gets
第二次fetch, 读第一块1行,此时产生第2次consistent gets,读第二块14行,此时产生第3次consistent gets
第三次fetch, 读第二块2行,此时产生第4次consistent gets,读第三块13行,此时产生第5次consistent gets
依此内推
假定此时表上每个数据块为10行,即数据块上的行数小于arraysize的情形(10<15)
第一次fetch,读第一块10行,此时产生第1次consistent gets
读第二块5行,此时产生第2次consistent gets
第二次fetch,读第二块5行,此时产生第3次consistent gets
读第三块10行,此时产生第4次consistent gets
第三次fetch,读第四块10行,此时产生第5次consistent gets
读第五块5行,此时产生第6次consistent gets
依此内推
当arraysize设置为n(15)时,则Oracle从buffer一次fetch n(15)行,然后将数据返回给客户端.接下来Oracle会再次从buffer中fetch第二次
,返回下一个n(15)行
由上可知,在fetch期间可能会产生多次consistent gets。
当设置了较大的arraysize,从演示中可以看出SQL*Net的sent与received也随之减少。即请求时往返的次数明显降低。
三、总结
1、arraysize参数用于控制返回给客户端预取的行数,缺省值为15
2、逻辑读为consistent gets + db block gets,为简化描述,下面直接使用逻辑读
3、当行预取值设定为1时,对于全表扫描,每返回一个行需要产生一个逻辑读,如果设定的行预取值大于单块存储的行数,则逻辑读接近于块数
4、逻辑读的值随arraysize的增大而减小,当达到临界值(即略大于表上单块存储的行束)之后其变化趋势不大
5、SQL*Net的sent与received的值会随着arraysize的增大而减小
6、逻辑读通常会多于一次,见第二点的分析
7、对于聚合运算的情形(无索引),SQL引擎内部使用行预取。即每次SQL引擎访问一个块的时候,抽取其中的所有行。其逻辑读接近于块数
8、在使用索引的情形下,consistent gets与arraysize无关
四、更多参考
dbms_xplan之display_cursor函数的使用