block size相关IO争议问题
Oct212013
今天在QQ群里,有人出了一道题,大家争论了半天,这道题是itpub论坛上的有奖问答题。

大家对AC有争议,争论了半天,最后决定亲自测试下来验证结果。至于BD两个选项,基本没什么争议,大家也都这么理解的。极端情况咱就不考虑了。下面主要测试下A选项,不考虑极端情况,C和A说的基本是同一个意思。(正确答案ABCD)
下面开始测试,先创建测试表空间。
SQL> create tablespace tbs8k datafile 'D:\APP\STREAM\ORADATA\DBDREAM\tbs8k.dbf 'size 10M blocksize 8K; 表空间已创建。 SQL> alter system set db_16k_cache_size=16384; 系统已更改。 SQL> create tablespace tbs16k datafile 'D:\APP\STREAM\ORADATA\DBDREAM\tbs16k.dbf 'size 10M blocksize 16K; 表空间已创建。
创建测试表。
SQL> create table tab8K tablespace tbs8K as select * from dba_objects; 表已创建。 SQL> create table tab16K tablespace tbs16K as select * from dba_objects; 表已创建。
查询tbs8k表的数据,看下统计信息。
SQL> select count(*) from tab8K;
COUNT(*)
----------
70828
执行计划
----------------------------------------------------------
Plan hash value: 558853398
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 283 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TAB8K | 80270 | 283 (1)| 00:00:04 |
--------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
28 recursive calls
0 db block gets
1092 consistent gets
1009 physical reads
0 redo size
425 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
可见,物理读1009,1009个数据块,每个块大小8K,1009*8=8072K。在看下tab16k这张表。
SQL> select count(*) from tab16K;
COUNT(*)
----------
70829
执行计划
----------------------------------------------------------
Plan hash value: 3797944160
---------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 194 (1)| 00:00:03 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TAB16K | 81695 | 194 (1)| 00:00:03 |
---------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
28 recursive calls
0 db block gets
582 consistent gets
498 physical reads
0 redo size
425 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
同样数据的表,16K的块物理读只有498,498个数据块每个块16K,498*16K=7968K。
对比下8K和16K块的表的执行信息:
| 对比项目 | Block Size 8K | Block Size 16K |
| Cost (%CPU) | 283 | 194 |
| Time | 00:00:04 | 00:00:03 |
| consistent gets | 1092 | 582 |
| physical reads | 1009 | 498 |
| physical reads*block size | 8072K | 7968K |
从上面的测试可以看出,存在8K的块的表全扫要I/O 1009次,而16K的表只需要I/O 498次,I/O次数明显减少,I/O读取的数据量(physical reads*block size)8K的读了8072K,16K的读了7968K,16K的块明显要比8K的块的少,这和表的数据存储空间需求有关。
SQL> select SEGMENT_NAME,bytes/1024 from dba_SEGMENTS where SEGMENT_name in ('TAB8K','TAB16K');
SEGMENT_NAME BYTES/1024
-------------------- ----------
TAB16K 8192
TAB8K 9216
可见,16K块的表空间存储一张数据完全一样的表要比8K块的表空间需要的空间要少。
所以,BLOCK越大,全表扫描的I/O越少是对的。
——————————————–end—————————————