PCTFREE和PCTUSED作用及举例

PCTFREE的作用是:当数据块的剩余容量达到PCTFREE值时,此数据块不再被记录于freelist中,不允许其他数据再存放至数据块中。

PCTUSED的作用是:当数据块中的数据量小于PCTUSED值时,此数据块将被记录于freelist中,允许其他数据再存放至此数据块中。

pctfree参数是控制freelist un-links的(即将块由freelists中移除)。设置pctfree=10 意味着每个块都保留10%的空间用作行扩展。

pctused参数是控制freelist re-links的。设置pctused=40意味着只有在块的使用低于40%时才会回到表格的freelists中。

PCTFREE和PCTUSED举例如下:

假设当前此两属性分别设置为PCTFREE=10,PCTUSED=80,则表示:


1、当数据块中的剩余容量小于10%时,此数据块不再记录于freelist中,不能再被插入数据,实际意义在于避免update操作将此块中的行使得行占用空间变大而导致行链接或者行迁移。


2、当此数据块的剩余容量大于20%时,此数据块被记录至freelist中,允许其他数据被插入。


PCTFREE和PCTUSED的值可以在创建表时指定,也可以在创建表后用修改,但是要注意的是,修改后的值,只对修改后的数据操作有影响,对之前的无效。


因为OLTP系统对数据块的DML操作会较为频繁,所以在OLTP系统中正确配置这两个属性可能会对性能有一定的提高。


在Oracle11g中,表空间默认使用本地位图自动管理,PCTFREE的默认值是10,且无法自定义管理PCTUSED属性,除非将表空间设置为手动管理。



实验一: 同一个表使用不同的PCTFREE和PCTUSED的值,所用BLOCK不同。

SQL> create tablespace users2 datafile 'f:\userdata\users2.dbf' size 10m autoextend on next 1m segment space management manual;


Tablespace created


SQL> drop tablespace users2 including contents and datafiles;


Tablespace dropped


SQL> create tablespace users2 datafile 'f:\userdata\users2.dbf' size 10m autoextend on next 1m segment space management manual;


Tablespace created


SQL> select * from tab;


TNAME                          TABTYPE  CLUSTERID


------------------------------ ------- ----------


SYS_TEMP_FBT                   TABLE  


SQL>  create table

test1 as select * from dba_objects;


Table created

需要手动执行命令进行表分析,来统计信息。如果不做的话,可能查不到表所占用的BLOCK信息。

如果不手动进行分析,系统会在 执行SQL的时候,自动采集样本统计信息,生成执行计划,此时为自动采集(SELECT也会采集)。这种自动采集过程,只收集一部分的样本数据用于统计信息,而手工收集是收集全部数据用于统计信息 ,因此后者计算的值更精确。

blocks的信息必须是收集完整的统计信息才能给出 精确的值
动态采集 只是收集一部分数据样本信息,目的:用这部分样本 模拟出 整个表的执行计划,这是一个相似值,因此不可以作为精确值使用
如果要想看,必须执行全表统计分析
常用命令
execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO1',
method_opt=>'for all indexed columns size 254');
ownname=>'LEO1'   表用户名
tabname=>'LEO1'    统计分析表名
对leo1进行全表整体分析包括数据分布情况分析(数据倾斜程度,即直方图)

SQL> analyze table test1 compute statistics;


Table analyzed

进行查询,此时  pct_free值是10. pct_used未设置。占用的BLOCK是1051个。

SQL>  select pct_free,pct_used,blocks,avg_row_len,chain_cnt from tabs where table_name='TEST1';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        10                 

1051         100          0


SQL>

alter table test1 pctfree 30;


Table altered


SQL> alter table test1

pctused 40;


Table altered


SQL> alter table test1 move tablespace users2;


Table altered


SQL>

analyze table test1 compute statistics;


Table analyzed

进行查询,此时  pct_free值是40. pct_used  40。占用的BLOCK是1320个。因为块的剩余小于40时不能再插入数据。故比“块剩余小于10%不能再插入数据多占用的近1/3的块

SQL> select PCT_FREE,PCT_USED,BLOCKS,AVG_ROW_LEN,CHAIN_CNT from tabs where table_name = 'TEST1';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        30         40      

1320         100          0


SQL>


实验二: 两个相同的表PCTUSED属性不同,删除同样一批数据后两个表所占用block的数量不同

结论是PCTUSED为 80的test3占用的block的数量明显比PCTUSED为40的test2占用的数量多。这是因为,删除同样的一大批数据后,Oracle会根据所操作块的PCTUSED属性判定此块是否可以被再次使用。test2的PCTUSED为40表示当块中的可用容量达到60%时,此块被标记为可用  ,而test3的PCTUSED为 80表示当块中的可用容量只要达到20%时,即可被标记为可用。这样如删除相同的数据,就会遇到test2 中的部分BLOCK可用容量低于60%,被标记为不可用,仍在占用着BLOCK。而test3中的BLOCK可用容量只要不低于20%,就会被插入数据,可以极大减少BLOCK使用量。实验如下:

SQL> create table test2 tablespace users2 as select * from test1 where 1=2;


Table created


SQL> create table test3 tablespace users2 as select * from test1 where 1=2;


Table created


SQL> select count(*) from test3;


  COUNT(*)


----------


         0


SQL> select count(*) from test2;


  COUNT(*)


----------


         0


SQL> alter table test2 pctfree 15;


Table altered


SQL>

alter table test2 pctused 40;


Table altered


SQL> alter table test3 pctfree 15;


Table altered


SQL>

alter table test3 pctused 80;


Table altered


SQL> insert into test2 select * from test1;


71976 rows inserted


SQL> insert into test3 select * from test1;


71976 rows inserted


SQL> select PCT_FREE,PCT_USED,BLOCKS,AVG_ROW_LEN,CHAIN_CNT from tabs where table_name = 'TEST2';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        15         40                        


SQL> analyze table test2 compute statistics;


Table analyzed


SQL> analyze table test3 compute statistics;


Table analyzed

此时两个表TEST2 TEST3所占用的BLOCK大小相等

SQL> select PCT_FREE,PCT_USED,BLOCKS,AVG_ROW_LEN,CHAIN_CNT from tabs where table_name = 'TEST2';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        15         40      

1083         100          0


SQL> select PCT_FREE,PCT_USED,BLOCKS,AVG_ROW_LEN,CHAIN_CNT from tabs where table_name = 'TEST3';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        15         80      

1083         100          0


说明首次插入数入数据时分配的block数量,不受PCT_FREE   PCT_USED 影响。


删除同样多的数据:


SQL> delete from test2 where owner='SYS';


30870 rows deleted


SQL> delete from test3 where owner='SYS';


30870 rows deleted


SQL> insert into test3 select * from test1;


71976 rows inserted


SQL> insert into test2 select * from test1;


71976 rows inserted


SQL> analyze table test3 compute statistics;


Table analyzed


SQL> analyze table test2 compute statistics;


Table analyzed


 此时可以观察到:

PCTUSED为 80的test3占用的block的数量明显比PCTUSED为40的test2占用的数量少。


SQL> select PCT_FREE,PCT_USED,BLOCKS,AVG_ROW_LEN,CHAIN_CNT from tabs where table_name = '

TEST3';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        15         80      1723         101          0


SQL> select PCT_FREE,PCT_USED,BLOCKS,AVG_ROW_LEN,CHAIN_CNT from tabs where table_name =

'TEST2';


  PCT_FREE   PCT_USED     BLOCKS AVG_ROW_LEN  CHAIN_CNT


---------- ---------- ---------- ----------- ----------


        15         40      2029         101          0