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—————————————