2007年6月28日星期四

《Expert one on one Oracle》- 表- 笔记-1

术语

高水位标示(HIGH WATER MARKET)

HWM是已经使用过的存储空间和未使用过的存储空间之间的分界线。在表刚创建的时候,HWM从第一数据块开始。随着数据插入的增多,HWM会上升。如果删除数据行,虽然部分被删除的哪些块不再包含数据,但是这些块仍然在HWM之下,HWM位置不会改变,直到HWM被重建或者TRUNCATE。ORACLE会扫描HWM下所有的块,即使这些块已经不包含数据。所以,这也会影响到性能。如果需要删除表中所有的行,尝试使用TRUNCATE。

FREELISTS

对于HWM下那些还有空闲空间的块,ORACLE使用FREELIST来记录。每个对象至少有一个FREELISTS。只有在HWM下的块才可以在FREELIST中找到。如果FREELISTS已经为空,那么HWM就会上移,新增块到FREELIST。一个对象可以拥有多个FREELIST。如果一个对象只有一个FREELIST,那么对于并发访问同一些的块,就会发生块等待事件。

但是也不是将FREELISTS设置越多越好。因为当一个进程用完一个FREELIST空闲块的时候,并不去使用这个对象的其他FREELIST的空闲块,而是上移HWM。如果当前的EXTENT不够,将会使用其他的EXTENT。所以,设置太多的FREELIST会造成空间上的浪费。

PCTFREE 和PCTUSED

这两个参数用来控制什么条件下将块加入FREELIST和从FREELIST中移除。PCTFREE默认的大小为10,意味着当块被使用了90%之后,将会从FREELIST中移除。剩下的10%的空间用于块中数据行的更新。PCTUSED的默认的大小为40,意味着对于那些不在FREELIST中的块,如果其空余空间达到61%的时候,ORACLE会将这些块重新加入到FREELIST中去。怎样设置这两个值需要根据数据处理情况,例如对于那些很少更新的数据,设置过大的PCTFREE是空间的浪费。

行迁移

由于行的更新,使得行所占用的空间增大,当行原来所在数据块空间不够容纳更新后的行,行必须迁移到新的数据块上。行迁移的过程,会将行的数据迁移到新的块,同时在原来块中保留指向新行的指针。这是因为索引的物理指针仍然需要知道原来数据行的地址。由于这样,行迁移会带来更多的I/O访问(访问原来所在块,然后再通过指针访问前以后所在的块)。

已经迁移到新块的行,由于被再次更新,新块的空余空间也不能容纳,这行将会再次迁移。如果原来的块中现在有足够的空间了,这行将会迁移回去。否则,将会迁移到第三个块上去。

PCTFREE 和PCTUSED设置

下面的例子看设置PCTFREE和PCTUSED怎样影响FREELIST。
SQL> create table t ( x int, y char(1000) default 'x' );
Table created.

SQL> create or replace procedure measure_usage
2 as
3 l_free_blks number;
4 l_total_blocks number;
5 l_total_bytes number;
6 l_unused_blocks number;
7 l_unused_bytes number;
8 l_LastUsedExtFileId number;
9 l_LastUsedExtBlockId number;
10 l_LAST_USED_BLOCK number;
11
12 procedure get_data
13 is
14 begin
15 dbms_space.free_blocks
16 ( segment_owner => USER,
17 segment_name => 'T',
18 segment_type => 'TABLE',
19 FREELIST_group_id => 0,
20 free_blks => l_free_blks );
21
22 dbms_space.unused_space
23 ( segment_owner => USER,
24 segment_name => 'T',
25 segment_type => 'TABLE',
26 total_blocks => l_total_blocks,
27 total_bytes => l_total_bytes,
28 unused_blocks => l_unused_blocks,
29 unused_bytes => l_unused_bytes,
30 LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
31 LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
32 LAST_USED_BLOCK => l_last_used_block ) ;
33
34
35 dbms_output.put_line( L_free_blks ' on FREELIST, '
36 to_number(l_total_blocks-l_unused_blocks-1 )

37 ' used by table' );
38 end;
39 begin
40 for i in 0 .. 10
41 loop
42 dbms_output.put( 'insert ' to_char(i,'00') ' ' );
43 get_data;
44 insert into t (x) values ( i );
45 commit ;
46 end loop;
47
48
49 for i in 0 .. 10
50 loop
51 dbms_output.put( 'update ' to_char(i,'00') ' ' );
52 get_data;
53 update t set y = null where x = i;
54 commit;
55 end loop;
56 end;
57 /
Procedure created.

SQL> exec measure_usage
insert 00 0 on FREELIST, 0 used by table
insert 01 1 on FREELIST, 1 used by table
insert 02 1 on FREELIST, 1 used by table
insert 03 1 on FREELIST, 1 used by table
insert 04 1 on FREELIST, 1 used by table
insert 05 1 on FREELIST, 1 used by table
insert 06 1 on FREELIST, 1 used by table
insert 07 1 on FREELIST, 1 used by table
insert 08 1 on FREELIST, 2 used by table--插入到第八行数据的时候,由于原来块上的空间不足,新增一个块供使用
insert 09 1 on FREELIST, 2 used by table
insert 10 1 on FREELIST, 2 used by table
update 00 1 on FREELIST, 2 used by table
update 01 1 on FREELIST, 2 used by table
update 02 1 on FREELIST, 2 used by table
update 03 1 on FREELIST, 2 used by table
update 04 2 on FREELIST, 2 used by table--更新到第四行的时候,将空间返回给FREELIST
update 05 2 on FREELIST, 2 used by table
update 06 2 on FREELIST, 2 used by table
update 07 2 on FREELIST, 2 used by table
update 08 2 on FREELIST, 2 used by table
update 09 2 on FREELIST, 2 used by table
update 10 2 on FREELIST, 2 used by table

PL/SQL procedure successfully completed.

INITIAL, NEXT, PCTINCREASE

定义初始EXTENT的大小以及后续EXTENT的大小。例如:INITIAL为1,NEXT为2,PCTINCREASE为为50,那么从EXTENT的一次大小为:1M,2M,3M,4.5M。如果数据库使用本地管理的表空间,EXTENT设置为UNIFORM的,那么INITIAL等于NEXT,PCTINCREASE没有意义。如果没有使用本地管理的表空间,也建议设置INITIAL等于NEXT,将PCTINCREASE设置为0。

MINEXTENTS,MAXEXTENTS

设置一个对象拥有最小和最大的EXTENT。当然,最大的EXTENT表空间的限制。

LOGGING,NOLOGGING

LOGGING,创建表的时候产生重做日志。使用NOLOGGING,创建表不产生重做日志,但是插入等操作仍然产生重做日志。

INITRANS,MAXTRANS

对象的每个块都有一个块头。块头中有一张事务表。在这张事务表中记录那些事务锁住了这个块上的那些行。初始值由INITRANS指定,最大值有MAXTRANS指定。

没有评论: