freelist是一种单向链表,oracle用它来管理oracle某个对象中位于高水位线下的空闲块,换句话说就是,通过 freelist,oracle可以定位这个对象可以使用哪些存储块来接受数据。每个对象至少有一个freelist,当存储块被使用 时,freelist中也将会有放入和取出的操作。需要注意一点的是,只有在低水位下的块才有可能在freelist中被发现。高水位的块被用到的情况, 只能在当freelist为空的时候,即低水位中无可用的存储块,才发生,这个时候,oracle会提高水位线的位置,并且把相应的块加到 freelist中。


当多个并行用户对于某对象执行insert或者update操作时,应多配几个freelist,这对于 oracle的性能是有帮助的。这是很明显的,因为可以避免空闲块的争用,以下会举例说明。当然freelist的数量也不是多多益善,需要根据并发数而 定,否则会浪费oracle的存储空间。通常每个进程只对应一个freelist,它不能从当前的freelist过渡到其他的freelist中去寻找 可用的存储块,也就是说呢,当对应它的freelist为空时,它只能通过调高HWM的位置,或者扩张extent、获取新的extent(当HWM到了 extent的尾部时)这两种方式来获取空闲的存储块。而绝对不会去其他的freelists中寻找空闲的存储块,即使也许其他的freelists中都 不为空。这样就明显浪费了oracle的空间;另外,freelist的过多也是oracle的性能瓶颈。

举例说明适当增加freelist的好处:

创建一个表create table t(x int);

为了通过数据反映问题,事先创建一个临时表

create temporary table p_stat_before

on commit perserve rows

as

select * from v$waitstat

where 1=0;

truncate table p_stat_before;

insert into p_stat_before

select * from v$waitstat;

开两个或者多个sessions同时做以下操作:

begin

for i in 1..100000

loop

insert into t values(i);

commit;

end loop;

end;

/

做完之后,运行一下脚步p_chech.sql

select a.class, b.count-a.count count, b.time-a.time time
from p_stat_before a, v$waitstat b
where a.class = b.class;

通常你会看到data block的count值会不为0,当freelist的数目满足不了并发用户数的时候。

因此,可以alter table t storage(freelists 2);来增加freelist的数量。

重复以上两sessions的操作,并且执行p_check.sql检查脚本,你会发现data block的值得到了改善,甚至为0。

posted on 2008-07-09 16:50  Alex.Zhang  阅读(1440)  评论(1编辑  收藏  举报