Hakan factor
Hakan factor 用来表示在表中任何一个数据块所包含的记录数量的上限。对于一个表来说,Hakan factor 受一下几方面的影响:
表中列的数量列的数量类型和长度列是否具有非空约束在通常情况下,oracle认为每条记录最小占用11byte的存储空间,这是为了在发生行迁移的情况下,留出足够的空间保存行迁移信息(扩展rowid会占用10字节的空间)。因此我们可以归纳出如下结论:
| 数据库大小 |
每块可以存储的最大记录数(抛出部分控制信息) |
| 2048 |
178(2048/11=186) |
| 4096 |
364(4096/11=194) |
| 8192 |
736(8192/11=744) |
| 16384 |
1481(16384/11=1489) |
| 32768 |
2971(32767/11=2978) |
下面我们来论证一下,(show_hakan函数来源于网络,函数的内容请参见文章底部):
SQL> create table tab1(c1 char(1));
表已创建。
SQL> execute show_hakan('tab1');
--Hakan factor for object 364291 (SCOTT.tab1) is 736 with flags 0
PL/SQL 过程已成功完成。
SQL> insert into tab1 select 'a' from dual connect by level < 1000;
已创建999行。
SQL> commit;
提交完成。
SQL> execute show_hakan('tab1');
--Hakan factor for object 364291 (SCOTT.tab1) is 736 with flags 0
PL/SQL 过程已成功完成。
SQL> create table tab2(c1 char(100),c2 char(300));
表已创建。
SQL> execute show_hakan('tab2');
--Hakan factor for object 364292 (SCOTT.tab2) is 736 with flags 0
PL/SQL 过程已成功完成。
SQL> insert into tab2 select 'a','b' from dual connect by level < 1000;
已创建999行。
SQL> commit;
提交完成。
SQL> execute show_hakan('tab2');
--Hakan factor for object 364292 (SCOTT.tab2) is 736 with flags 0
PL/SQL 过程已成功完成。
SQL> alter table tab2 modify c1 not null;
表已更改。
SQL> alter table tab2 modify c2 not null;
表已更改。
SQL> execute show_hakan('tab2');
--Hakan factor for object 364292 (SCOTT.tab2) is 19 with flags 0
PL/SQL 过程已成功完成。 从上面的情况也可以看出,oracle在计算 hakan factor时,是以可能发生的最大值为其计算结果。
alter table minimize records_per_block
oracle并没有为我们提供显示修改或者查看hakan factor的功能,但是我们可以通过一些变通的方式来实现这些功能。alter table ... minimize RECOREDS_PER_BLOCK的工作过程如下:
扫描整个表计算表中每个块中包含的记录数量设置表的hakan factor为块记录数量的最大值设置标志位为ox8000(),表示表的hakan factor通过records_per_block设置
通过recors_per_block设置hakan factor 后,当我们后续向表中添加记录时,每个数据块的记录数不会超过hakan factor设置的值。
SQL> create table tab1(c1 number);
表已创建。
SQL> alter table tab1 minimize records_per_block;
alter table tab1 minimize records_per_block
*
--第 1 行出现错误:
--ORA-28603: 不允许对空表使用语句
SQL> insert into tab1 values(1);
已创建 1 行。
SQL> commit;
提交完成。
SQL> insert into tab1 select * from tab1;
已创建 1 行。
SQL> /
已创建2行。
SQL> commit;
提交完成。
SQL> alter table tab1 minimize records_per_block;
表已更改。
SQL> execute show_hakan('tab1');
Hakan factor for object 364293 (SCOTT.tab1) is 3 with flags 8000
PL/SQL 过程已成功完成。
SQL> insert into tab1 select * from tab1;
已创建4行。
SQL> /
已创建8行。
SQL> commit;
提交完成。
SQL> select
ct, count(*)
from (
Select Dbms_Rowid.Rowid_Block_Number(Rowid), Count(*) Ct
from tab1
group by
dbms_rowid.rowid_block_number(rowid)
)
Group By Ct
order by ct 2 3 4 5 6 7 8 9 10
11 /
CT COUNT(*)
---------- ----------
4 4
SQL> create bitmap index i1 on tab1(c1);
索引已创建。
SQL> alter table tab1 nominimize records_per_block;
alter table tab1 nominimize records_per_block
*
第 1 行出现错误:
ORA-28602: 不允许对包含位图索引的表使用语句
SQL> create table tab2(c1 number);
表已创建。
SQL> create bitmap index i2 on tab2(c1);
索引已创建。
SQL> insert into tab2 values(1);
已创建 1 行。
SQL> commit;
提交完成。
SQL> alter table tab2 minimize records_per_block;
alter table tab2 minimize records_per_block
*
--第 1 行出现错误:
--ORA-28602: 不允许对包含位图索引的表使用语句
SYS.TAB$.SPARE1
oracle没有给我们提供直接的视图来查询hakan factor