consistent gets

前段时间在测试高级压缩在IO方面性能的时候发现一个疑问,先看看当时的场景

SQL> select table_name,num_rows,blocks from user_tab_statistics where table_name in('COMTAB'
,'NOCOMTAB');
TABLE_NAME			 NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
COMTAB				    71991	 342
NOCOMTAB			    71992	1051
这是两个表最新的统计信息,数据完全一样(差那一条是建表先后顺序造成的),comtab是启用高级压缩的,nocomtab没有压缩,下面看看两个表的全表扫描情况

SQL> set autotrace trace
SQL> select * from comtab;

71991 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1463407995

----------------------------------------------------------------------------
| Id  | Operation	  | Name   | Rows  | Bytes | Cost (%CPU)| Time	   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	   | 71991 |  6819K|	95   (2)| 00:00:02 |
|   1 |  TABLE ACCESS FULL| COMTAB | 71991 |  6819K|	95   (2)| 00:00:02 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
	  1  recursive calls
	  0  db block gets
       5109  consistent gets
	  0  physical reads
	  0  redo size
    3720394  bytes sent via SQL*Net to client
      53313  bytes received via SQL*Net from client
       4801  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
      71991  rows processed

SQL> select * from nocomtab;

71992 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 754113270

------------------------------------------------------------------------------
| Id  | Operation	  | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	     | 71992 |	6819K|	 287   (1)| 00:00:04 |
|   1 |  TABLE ACCESS FULL| NOCOMTAB | 71992 |	6819K|	 287   (1)| 00:00:04 |
------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
	  1  recursive calls
	  0  db block gets
       5768  consistent gets
	  0  physical reads
	  0  redo size
    8254868  bytes sent via SQL*Net to client
      53313  bytes received via SQL*Net from client
       4801  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
      71992  rows processed

刚开始我认为两个表在数据块数量相差如此大的情况下,consistent gets的数量应该也有相当大的差距,但是现在看来,差距是有,却不是那么明显,很多疑问也出来了

1,consistent gets到底是次数还是块数?

2,consistent gets是怎么计算的?

3,三百多数据块为什么产生五千多的一致性读?

4,两个表的数据块比例达到了1/3,一致性读的比例却接近1/1?


块数or次数

以前我只关心consistent gets前面的数值,至于数值后面的单位是什么,根本没去管,现在这么个情况不管不行了,在我个人看来,我更倾向于consistent gets是一致性读次数,而不是块数,就拿这个例子来说,全部数据才300多个数据块,oracle扫描300多个数据块不至于递归调用5000多数据块吧,所以我认为是这5000多是一致性读次数,后面会有实验证明

consistent gets计算

在查询操作中,oracle按照执行计划去读取数据块,数据块只能存在两个地方,内存和磁盘,对应的也就是逻辑读和物理读,consistent gets就是数据库在内存中为了获取指定的数据产生的一致性读次数,而不是块数,同一个数据块可以读多次而不是获取多次,一致性读概念这里就不解释了,在全表扫描中,理想情况下consistent gets应该和表的总数据块数差不多或者接近,下面做个测试

创建一个表,插入一条数据

SQL> create table test01 as select * from dba_objects where rownum=1;

Table created.

SQL> begin
  2  dbms_stats.gather_table_stats(
  3  ownname => user,
  4  tabname => 'test01');
  5  end;
  6  /

PL/SQL procedure successfully completed.

test01占用4个数据块

SQL> select table_name,num_rows,blocks from user_tab_statistics where table_name='TEST01';

TABLE_NAME			 NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
TEST01					1	   4

执行全表扫描

SQL> set autotrace trace
SQL> select * from test01;


Execution Plan
----------------------------------------------------------
Plan hash value: 262542483

----------------------------------------------------------------------------
| Id  | Operation	  | Name   | Rows  | Bytes | Cost (%CPU)| Time	   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	   |	 1 |	73 |	 3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| TEST01 |	 1 |	73 |	 3   (0)| 00:00:01 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
	  1  recursive calls
	  0  db block gets
	  3  consistent gets
	  0  physical reads
	  0  redo size
       1608  bytes sent via SQL*Net to client
	524  bytes received via SQL*Net from client
	  2  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

4个数据块,3个consistent gets,这才是我们想要的效果,那之前300多个数据块5000多次一致性读是怎么回事呢,后来查阅资料发现,oracle从数据库读取数据行发送给sqlplus客户端的时候有个参数设置,这个参数就是arraysize,用来控制每次读取数据的行数,在sqlplus里面默认是15

SQL> show arraysize
arraysize 15
现在来计算一下前面那个5109个consistent gets怎么来的

数据行:71991

数据块:342  

arraysize:15

总读取次数:71991/15 = 4800

总读取次数:4800 + 342 = 5142

这个数值已经很接近consistent gets了,而且全表扫描时表的数据块不会被全部读进内存,这样计算出来的值跟一致性读的值就更吻合了

现在改变arrarysize这个参数,看看consistent gets会有什么变化

SQL> set arraysize 100
SQL> select * from comtab;

71991 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1463407995

----------------------------------------------------------------------------
| Id  | Operation	  | Name   | Rows  | Bytes | Cost (%CPU)| Time	   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	   | 71991 |  6819K|	95   (2)| 00:00:02 |
|   1 |  TABLE ACCESS FULL| COMTAB | 71991 |  6819K|	95   (2)| 00:00:02 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
	  0  recursive calls
	  0  db block gets
       1047  consistent gets
	  0  physical reads
	  0  redo size
    2973754  bytes sent via SQL*Net to client
       8432  bytes received via SQL*Net from client
	721  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
      71991  rows processed
计算:71991/100=720  ,   720 + 342 = 1062  
增加arraysize大小,可以显著减少逻辑读次数,网络开销也有减少,同时也能看出,由于arraysize只有15,前面那两个5000多逻辑读的场景,大部分逻辑读是在不停的扫描同一个数据块获取数据,arraysize只在sqlplus客户端中用,其他地方使用fetch size,该参数大小设置影响客户端和服务器内存的占用,应根据实际环境配置,总之不是越大越好。

至此,疑问也基本上理清了

1,consistent gets是次数,认为是块数也行,不过可能会包含同一个块的重复计数

2,这个数据库没有对这个表做DML操作,所以consistent gets没有包括undo块

3,5000多逻辑读有4800个是由于arraysize参数设置引起的

4,还是arraysize问题,如果设置成5000,比例就差不多了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值