SQLplus 下行预取特性

通常情况下数据库引擎每访问一个数据块将产生至少一个逻辑读。而行预取与逻辑读息息相关。行预取是指当客户端从数据库获取数据时
可以采用单行也可以采用多行方式返回数据。当采用多行方式时,则会预取多条记录存储在客户端内存中以避免后续多次该数据的请求所致的
各种开销(LIO,PIO,NET IO)。一般预取行数越大,则所产生的开销越小,当达到临界值时其变化不大。
一、演示
  1. 1、创建演示表 
  2.     scott@CNMMBO> select * from v$version where rownum<2; 
  3.      
  4.     BANNER 
  5.     ---------------------------------------------------------------- 
  6.     Oracle Database 10g Release 10.2.0.3.0 - 64bit Production 
  7.     scott@CNMMBO> create table t as select * from dba_objects;   -->创建演示表 
  8.      
  9.     scott@CNMMBO> analyze table t compute statistics;            -->更新统计信息 
  10.      
  11.     scott@CNMMBO> exec show_space('T'); 
  12.     Unformatted Blocks .....................               0 
  13.     FS1 Blocks (0-25) ......................               0 
  14.     FS2 Blocks (25-50) .....................               0 
  15.     FS3 Blocks (50-75) .....................               0 
  16.     FS4 Blocks (75-100).....................               0 
  17.     Full Blocks ............................             690 
  18.     Total Blocks............................             768    -->表段上的总块数768 
  19.     Total Bytes.............................       6,291,456 
  20.     Total MBytes............................               6 
  21.     Unused Blocks...........................              58    -->未使用的块数58 
  22.     Unused Bytes............................         475,136 
  23.     Last Used Ext FileId....................              11 
  24.     Last Used Ext BlockId...................          39,561 
  25.     Last Used Block.........................              70 
  26.      
  27.     PL/SQL procedure successfully completed. 
  28.  
  29. 2、arraysize与consistent gets的关系 
  30.     scott@CNMMBO> show arraysize                 -->arraysize的大小此时为默认值15 
  31.     arraysize 15 
  32.     scott@CNMMBO> set arraysize 2                -->修改arraysize的值为2 
  33.     scott@CNMMBO> set autotrace traceonly stat;  -->启用autotrace    
  34.     scott@CNMMBO> select * from t; 
  35.      
  36.     Statistics 
  37.     ---------------------------------------------------------- 
  38.               1  recursive calls 
  39.               0  db block gets 
  40.           25390  consistent gets                -->此时的consistent gets为25390 
  41.               0  physical reads 
  42.               0  redo size 
  43.         6596152  bytes sent via SQL*Net to client 
  44.          275844  bytes received via SQL*Net from client 
  45.           25034  SQL*Net roundtrips to/from client 
  46.               0  sorts (memory) 
  47.               0  sorts (disk) 
  48.           50066  rows processed 
  49.      
  50.     scott@CNMMBO> set arraysize 15              -->修改arraysize的值为15 
  51.     scott@CNMMBO> select * from t; 
  52.      
  53.     Statistics 
  54.     ---------------------------------------------------------- 
  55.               0  recursive calls 
  56.               0  db block gets 
  57.            3992  consistent gets                -->此时的consistent gets为3992 
  58.               0  physical reads 
  59.               0  redo size 
  60.         2625967  bytes sent via SQL*Net to client 
  61.           37199  bytes received via SQL*Net from client 
  62.            3339  SQL*Net roundtrips to/from client 
  63.               0  sorts (memory) 
  64.               0  sorts (disk) 
  65.           50066  rows processed 
  66.  
  67. --从上面的演示可以看出由于设置了不同的array size值,导致在全表扫描(表上不存在索引)是产生了不同的consistent gets 
  68. --当arraysize值变大时,consistent gets的值会减少 
  69. --consistent gets 为3992从何而来? 
  70.  
  71.     scott@CNMMBO> set autotrace off
  72.     scott@CNMMBO> select 50066/15+768-58 from dual;  -->number_of_rows/arraysize + total_blocks_read  
  73.      
  74.     50066/15+768-58 
  75.     --------------- 
  76.          4047.73333 
  77.           
  78. --从上面的计算可以看出4047若高于3992,因此该consistent gets接近于计算得到的值 
  79.  
  80.     scott@CNMMBO> set autotrace traceonly; 
  81.     scott@CNMMBO> select count(*) from t;           -->聚合计算 
  82.      
  83.     Execution Plan 
  84.     ---------------------------------------------------------- 
  85.     Plan hash value: 2966233522 
  86.      
  87.     ------------------------------------------------------------------- 
  88.     | Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     | 
  89.     ------------------------------------------------------------------- 
  90.     |   0 | SELECT STATEMENT   |      |     1 |   158   (1)| 00:00:02 | 
  91.     |   1 |  SORT AGGREGATE    |      |     1 |            |          | 
  92.     |   2 |   TABLE ACCESS FULL| T    | 50066 |   158   (1)| 00:00:02 | 
  93.     ------------------------------------------------------------------- 
  94.      
  95.     Statistics 
  96.     ---------------------------------------------------------- 
  97.               0  recursive calls 
  98.               0  db block gets 
  99.             695  consistent gets                -->此时的consistent gets为695 
  100.               0  physical reads 
  101.               0  redo size 
  102.             517  bytes sent via SQL*Net to client 
  103.             492  bytes received via SQL*Net from client 
  104.               2  SQL*Net roundtrips to/from client 
  105.               0  sorts (memory) 
  106.               0  sorts (disk) 
  107.               1  rows processed 
  108.      
  109.     --此时走的是全表扫描,为什么一致读仅仅只有695?接近于表上的块数. 
  110.     --考虑表段上的块数768-58=710 
  111.     --注意此时的聚合仅仅是一个SINGLE CALL,SQL引擎内部使用行预取,每个块上将产生一次逻辑读,抽取其中的所有行     
  112.      
  113.     scott@CNMMBO> set autotrace off
  114.     scott@CNMMBO> SELECT num_rows, 
  115.       2    blocks blks, 
  116.       3    empty_blocks em_blks, 
  117.       4    avg_space, 
  118.       5    chain_cnt, 
  119.       6    avg_row_len, 
  120.       7    round(num_rows / blocks) AS avg_rows_per_block, 
  121.       8    last_analyzed lst_anly, 
  122.       9    stale_stats 
  123.      10  FROM   dba_tab_statistics 
  124.      11  WHERE  table_name = 'T' 
  125.      12  AND owner = 'SCOTT'
  126.      
  127.       NUM_ROWS       BLKS    EM_BLKS  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY  STA 
  128.     ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- --- 
  129.          50066        710         58        860          0          97                 71 12-JAN-12 NO 
  130.      
  131.     scott@CNMMBO> select 71*710 from dual; 
  132.      
  133.         71*710 
  134.     ----------            -->值50410与50066相接近 
  135.          50410 
  136.  
  137. 3、arraysize与全表扫描     
  138.     scott@CNMMBO> set autotrace traceonly stat; 
  139.     scott@CNMMBO> set arraysize 100       -->调整arraysize值为100 
  140.     scott@CNMMBO> select * from t; 
  141.      
  142.     Statistics 
  143.     ---------------------------------------------------------- 
  144.               0  recursive calls 
  145.               0  db block gets 
  146.            1185  consistent gets 
  147.               0  physical reads 
  148.               0  redo size 
  149.         2106796  bytes sent via SQL*Net to client 
  150.            5992  bytes received via SQL*Net from client 
  151.             502  SQL*Net roundtrips to/from client 
  152.               0  sorts (memory) 
  153.               0  sorts (disk) 
  154.           50066  rows processed 
  155.      
  156.     scott@CNMMBO> set arraysize 200       -->调整arraysize值为200   
  157.     scott@CNMMBO> select * from t; 
  158.      
  159.     Statistics 
  160.     ---------------------------------------------------------- 
  161.               0  recursive calls 
  162.               0  db block gets 
  163.             940  consistent gets 
  164.               0  physical reads 
  165.               0  redo size 
  166.         2061046  bytes sent via SQL*Net to client 
  167.            3242  bytes received via SQL*Net from client 
  168.             252  SQL*Net roundtrips to/from client 
  169.               0  sorts (memory) 
  170.               0  sorts (disk) 
  171.           50066  rows processed 
  172.      
  173.     scott@CNMMBO> set arraysize 2000      -->调整arraysize值为2000,此时访问方式为全表扫描 
  174.     scott@CNMMBO> select * from t; 
  175.      
  176.     Statistics 
  177.     ---------------------------------------------------------- 
  178.               0  recursive calls 
  179.               0  db block gets 
  180.             721  consistent gets 
  181.               0  physical reads 
  182.               0  redo size 
  183.         2019871  bytes sent via SQL*Net to client 
  184.             767  bytes received via SQL*Net from client 
  185.              27  SQL*Net roundtrips to/from client 
  186.               0  sorts (memory) 
  187.               0  sorts (disk) 
  188.           50066  rows processed 
  189.      
  190.     scott@CNMMBO> set arraysize 4000      -->调整arraysize值为4000,此时访问方式为全表扫描 
  191.     scott@CNMMBO> select * from t; 
  192.      
  193.     Statistics 
  194.     ---------------------------------------------------------- 
  195.               0  recursive calls 
  196.               0  db block gets 
  197.             708  consistent gets 
  198.               0  physical reads 
  199.               0  redo size 
  200.         2017492  bytes sent via SQL*Net to client 
  201.             624  bytes received via SQL*Net from client 
  202.              14  SQL*Net roundtrips to/from client 
  203.               0  sorts (memory) 
  204.               0  sorts (disk) 
  205.           50066  rows processed  
  206.      
  207.     scott@CNMMBO> set arraysize 20000     -->调整arraysize超出范围 
  208.     SP2-0267: arraysize option 20000 out of range (1 through 5000) 
  209.     scott@CNMMBO> set arraysize 5000      -->调整arraysize到最大值5000,此时访问方式为全表扫描 
  210.     scott@CNMMBO> select * from t; 
  211.      
  212.     Statistics 
  213.     ---------------------------------------------------------- 
  214.               0  recursive calls 
  215.               0  db block gets 
  216.             706  consistent gets 
  217.               0  physical reads 
  218.               0  redo size 
  219.         2017126  bytes sent via SQL*Net to client 
  220.             602  bytes received via SQL*Net from client 
  221.              12  SQL*Net roundtrips to/from client 
  222.               0  sorts (memory) 
  223.               0  sorts (disk) 
  224.           50066  rows processed  
  225.                  
  226. --从上面观察可以看出当arraysize不但增大的情形下,其逻辑读相应会减少,当arraysize达到一定值之后逻辑读减少的幅度变化不大 
  227.        
  228.     scott@CNMMBO> set autotrace traceonly;  
  229.     scott@CNMMBO> show arraysize  
  230.     arraysize 1 
  231.     scott@CNMMBO> select * from emp; 
  232.      
  233.     Execution Plan 
  234.     ---------------------------------------------------------- 
  235.     Plan hash value: 3956160932 
  236.      
  237.     -------------------------------------------------------------------------- 
  238.     | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     | 
  239.     -------------------------------------------------------------------------- 
  240.     |   0 | SELECT STATEMENT  |      |    14 |   518 |     3   (0)| 00:00:01 | 
  241.     |   1 |  TABLE ACCESS FULL| EMP  |    14 |   518 |     3   (0)| 00:00:01 | 
  242.     -------------------------------------------------------------------------- 
  243.      
  244.     Statistics 
  245.     ---------------------------------------------------------- 
  246.               0  recursive calls 
  247.               0  db block gets 
  248.              14  consistent gets 
  249.               0  physical reads 
  250.               0  redo size 
  251.            2633  bytes sent via SQL*Net to client 
  252.             558  bytes received via SQL*Net from client 
  253.               8  SQL*Net roundtrips to/from client 
  254.               0  sorts (memory) 
  255.               0  sorts (disk) 
  256.              14  rows processed      
  257. --从上面的测试可以看出在全表扫描时,当arraysize为1时,表上的一条记录将产生一次consistent gets   
  258.               
  259. 3、arraysize与索引扫描 
  260.     scott@CNMMBO> alter table t add constraint t_pk primary key(object_id);  -->为表添加索引 
  261.      
  262.     scott@CNMMBO> analyze table t compute statistics;                        -->更新统计信息 
  263.      
  264.     scott@CNMMBO> set autotrace traceonly;  
  265.     scott@CNMMBO> select count(*) from t; 
  266.      
  267.     Execution Plan 
  268.     ---------------------------------------------------------- 
  269.     Plan hash value: 454320086 
  270.      
  271.     ---------------------------------------------------------------------- 
  272.     | Id  | Operation             | Name | Rows  | Cost (%CPU)| Time     | 
  273.     ---------------------------------------------------------------------- 
  274.     |   0 | SELECT STATEMENT      |      |     1 |    24   (0)| 00:00:01 | 
  275.     |   1 |  SORT AGGREGATE       |      |     1 |            |          | 
  276.     |   2 |   INDEX FAST FULL SCAN| T_PK | 50066 |    24   (0)| 00:00:01 | 
  277.     ---------------------------------------------------------------------- 
  278.      
  279.     Statistics 
  280.     ---------------------------------------------------------- 
  281.               1  recursive calls 
  282.               0  db block gets 
  283.             111  consistent gets 
  284.               0  physical reads 
  285.               0  redo size 
  286.             517  bytes sent via SQL*Net to client 
  287.             492  bytes received via SQL*Net from client 
  288.               2  SQL*Net roundtrips to/from client 
  289.               0  sorts (memory) 
  290.               0  sorts (disk) 
  291.               1  rows processed 
  292.                
  293.     --从上面的执行计划和buffers可以看出此时走了索引全扫描,且consistent gets的大小为111.即优化器基于索引统计得到总行数,而不是基于表. 
  294.      
  295.     scott@CNMMBO> exec show_space('T_PK''SCOTT''INDEX');         -->查看索引段的使用情况 
  296.     Unformatted Blocks .....................               0 
  297.     FS1 Blocks (0-25) ......................               0 
  298.     FS2 Blocks (25-50) .....................               1 
  299.     FS3 Blocks (50-75) .....................               0 
  300.     FS4 Blocks (75-100).....................               0 
  301.     Full Blocks ............................             104 
  302.     Total Blocks............................             120       -->索引段总块数120       
  303.     Total Bytes.............................         983,040 
  304.     Total MBytes............................               0 
  305.     Unused Blocks...........................               5       -->空闲块数为5 
  306.     Unused Bytes............................          40,960 
  307.     Last Used Ext FileId....................              11 
  308.     Last Used Ext BlockId...................          39,745 
  309.     Last Used Block.........................               3 
  310.      
  311.     PL/SQL procedure successfully completed. 
  312.  
  313.     scott@CNMMBO> show arraysize  
  314.     arraysize 5000   
  315.     scott@CNMMBO> select count(*) from t; 
  316.      
  317.     Statistics 
  318.     ---------------------------------------------------------- 
  319.               0  recursive calls 
  320.               0  db block gets 
  321.             111  consistent gets 
  322.               0  physical reads 
  323.               0  redo size 
  324.             517  bytes sent via SQL*Net to client 
  325.             492  bytes received via SQL*Net from client 
  326.               2  SQL*Net roundtrips to/from client 
  327.               0  sorts (memory) 
  328.               0  sorts (disk) 
  329.               1  rows processed 
  330.      
  331.     scott@CNMMBO> set arraysize 2000 
  332.     scott@CNMMBO> select count(*) from t; 
  333.      
  334.     Statistics 
  335.     ---------------------------------------------------------- 
  336.               0  recursive calls 
  337.               0  db block gets 
  338.             111  consistent gets 
  339.               0  physical reads 
  340.               0  redo size 
  341.             517  bytes sent via SQL*Net to client 
  342.             492  bytes received via SQL*Net from client 
  343.               2  SQL*Net roundtrips to/from client 
  344.               0  sorts (memory) 
  345.               0  sorts (disk) 
  346.               1  rows processed 
  347.      
  348.     scott@CNMMBO> set arraysize 15 
  349.     scott@CNMMBO> select count(*) from t; 
  350.      
  351.     Statistics 
  352.     ---------------------------------------------------------- 
  353.               0  recursive calls 
  354.               0  db block gets 
  355.             111  consistent gets 
  356.               0  physical reads 
  357.               0  redo size 
  358.             517  bytes sent via SQL*Net to client 
  359.             492  bytes received via SQL*Net from client 
  360.               2  SQL*Net roundtrips to/from client 
  361.               0  sorts (memory) 
  362.               0  sorts (disk) 
  363.               1  rows processed 
  364.      
  365.     scott@CNMMBO> set arraysize 1 
  366.     scott@CNMMBO> select count(*) from t; 
  367.      
  368.     Statistics 
  369.     ---------------------------------------------------------- 
  370.               0  recursive calls 
  371.               0  db block gets 
  372.             111  consistent gets 
  373.               0  physical reads 
  374.               0  redo size 
  375.             517  bytes sent via SQL*Net to client 
  376.             492  bytes received via SQL*Net from client 
  377.               2  SQL*Net roundtrips to/from client 
  378.               0  sorts (memory) 
  379.               0  sorts (disk) 
  380.               1  rows processed 
  381.                
  382. --从上面的测试可知,走索引扫描之后的聚合与arraysize无关 


二、分析
  假定使用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无关

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值