在<<分析以及测试PCTFREE和PCTUSED参数是如何协调工作的>>文章中测试时对 free lists采用的默认的类型,没有多考虑 free lists类型改变对性能的影响,下面想通过测试通过定义表的时候定义的参数FREELISTS >=2,来使用多个free list 就可以分摊空闲空间的管理方式,看是否可以执行操作提高性能?
简单介绍下 free list的类别 :
2.3 free list类别
在段中存在3类free list, 即Master Freelists (MFL), Process Freelists (PrFL), 和 Transaction Freelists.
2.3.1 Master Free List(公用空闲空间池):
每一个段中有一个Master free list,在段创建的时候自动生成。对于每一个段来说都有这样一个空闲空间池,对每个进程都是公用的,空闲空间就是位于master free list 的块上。由于Master free list是公用的,因此当多个进程同时插入行到同一个段上,master free list竞争使用程度就会增加。
2.3.2 Process Free Lists
为了减少Master Free list的竞争问题, 引入了另一种free list叫做Process free lists, 根据sql命令 CREATE/ALTER 中的参数FREELISTS 创建. 这样多个free list 就可以分摊空闲空间的管理,以提高OLTP应用作高度并发插入和更新事务时空间分配管理的性能。通过指定CREATE TABLE / CLUSTER or INDEX的子句STORAGE的参数FREELISTS 来创建,例如: CREATE TABLE flg ( . . . .) . . . STORAGE ( ... FREELISTS 10 ...)。缺省的FREELISTS为1,此时不会创建Process free lists。当FREELISTS>=2时,创建Process free lists。
进程在使用process free list是根据进程的Oracle PID (Process ID)来选择的,公式如下:
select list entry = (PID % NFL) + 1
NFL : FREELISTS定义的Process free list个数
2.3.3 Transaction Free Lists
当Oracle需要时动态创建。一个Transaction Free List 是一种专门给某一个事务使用的free list. 每个段至少有16个transactions free lists, 并且这个值在需要时会增长,直到达到Segment Header块的大小限制。一个事务只有下面情况下会需要分配一个Tx Free Lists entry: 块中释放空间时(DELETE or UPDATE) 并且还不存在Tx Free Lists entry时。
比较测试:
1、新建两张表,一个是采用单个freelist管理,即采用的是 Master Free List(公用空闲空间池): 另一个采用多个freelist管理,即采用Process Free Lists ;
-- Create table
create table TT
(
X INTEGER,
Y CHAR(1000) default 'x'
)
tablespace TBS_DAIMIN
pctfree 10
pctused 40
initrans 1
maxtrans 255
storage
(
initial 64K
FREELISTS 8
minextents 1
maxextents unlimited
);
-- Create table
create table T
(
X INTEGER,
Y CHAR(1000) default 'x'
)
tablespace TBS_DAIMIN
pctfree 10
pctused 80
initrans 1
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
2、下面是执行操作代码,我测试时是在两个session中同时执行同样的代码,即每段代码执行了两遍:
首先新建一张表用来记录执行时间
create table testinfo
(PKID number,
usestarttime timestamp,
useendtime timestamp,
executetime date,
pro_name varchar2(10));
对T表操作:
declare
startdate timestamp;
enddate timestamp;
excutetime date;
m_count number;
procedure Inserttestexetime(n number, starttime timestamp,endtime timestamp,exetime date,v_pro_name varchar2) IS
begin
insert into testinfo(PKID,usestarttime,useendtime,executetime,pro_name) values(n,starttime,endtime,exetime,v_pro_name);
commit;
end Inserttestexetime;
begin
m_count:=0;
startdate:=systimestamp;
for i in 1..50 loop
for i in 0..20
loop
--show_space('T');
insert into T(x,y) values(i,to_char(i,'00'));
commit;
end loop;
m_count:=m_count+1;
end loop;
enddate:=systimestamp;
Inserttestexetime(m_count,startdate,enddate,excutetime,'T');
end;
对TT表进行操作:
declare
startdate timestamp;
enddate timestamp;
excutetime date;
m_count number;
procedure Inserttestexetime(n number, starttime timestamp,endtime timestamp,exetime date,v_pro_name varchar2) IS
begin
insert into testinfo(PKID,usestarttime,useendtime,executetime,pro_name) values(n,starttime,endtime,exetime,v_pro_name);
commit;
end Inserttestexetime;
begin
m_count:=0;
excutetime:=sysdate;
startdate:=systimestamp;
for j in 1..50 loop
for i in 0..20
loop
--show_space('TT');
insert into TT(x,y) values(i,to_char(i,'00'));
commit;
end loop;
m_count:=m_count+1;
end loop;
enddate:=systimestamp;
Inserttestexetime(m_count,startdate,enddate,excutetime,'TT');
end;
执行时间结果是:
SELECT t.pkid,
t.pro_name,
EXTRACT(second FROM(t.useendtime - t.usestarttime)) +
EXTRACT(minute FROM(t.useendtime - t.usestarttime)) * 60
from testinfo t;
PKID PRO_NAME
---------- ----------
EXTRACT(SECONDFROM(T.USEENDTIME-T.USESTARTTIME))+EXTRACT(MINUTEFROM(T.USEENDTIME
--------------------------------------------------------------------------------
50 TT
18.573404
50 TT
16.650209
50 T
9.601368
PKID PRO_NAME
---------- ----------
EXTRACT(SECONDFROM(T.USEENDTIME-T.USESTARTTIME))+EXTRACT(MINUTEFROM(T.USEENDTIME
--------------------------------------------------------------------------------
50 T
13.155673
从执行所需要的时间比较上发现多个free list 就可以分摊空闲空间的管理并没有提高插入或者更新的性能,是否是我的理解有误?大家帮忙看看呢:)