Hakanfactor
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 0PL/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 0PL/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 0PL/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 0PL/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 0PL/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 8000PL/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 Ctorder by ct 2 3 4 5 6 7 8 9 10 11 / CT COUNT(*)---------- ---------- 4 4SQL> 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,我们可以通过手工解析表SYS.TAB$的spare1字段来获取有个hakan factor的信息。下面对spare1字段内容的解释来源与网络
Lower bits (at least 12, perhaps as many as 15): H?kan factor. 0×08000: MINIMIZE RECORDS_PER_BLOCK in effect0×10000: Seems to mean that the H?kan factor has been fixed higher than the value calculated from non-null columns. This could be e.g. if set by event 14529 (see below) or if non-null columns have been added after a bitmap index has been created.0×20000: Table compression is enabled 综上,我们可以使用下面的过程来查看hakan factorcreate or replace procedure show_hakan( i_table in varchar2, i_owner in varchar2 default user) as m_obj number(8,0); m_flags varchar2(12); m_hakan number(8,0);begin select obj#, to_char( bitand( spare1, to_number('ffff8000','xxxxxxxx') ), 'xxxxxxxx' ) flags, bitand(spare1, 32767) hakan -- 0x7fff into m_obj, m_flags, m_hakan from tab$ where obj# in ( select object_id from dba_objects where object_name = upper(i_table) and object_type = 'TABLE' and owner = upper(i_owner) ) ; dbms_output.put_line( 'Hakan factor for object ' || m_obj || ' (' || i_owner || '.' || i_table || ') is ' || m_hakan || ' with flags ' || m_flags );end;/drop public synonym show_hakan;Create Public Synonym Show_Hakan For Show_Hakan;grant execute on show_hakan to public;
Hakan factor 对位图索引的影响
我们知道位图索引是通过起始rowid和结束rowid和位图的联合作用来定位数据。因此,我们处理需要知道起始rowid和终止rowid之外,还需要知道在每个数据块中的记录数量,而这往往是很难做到的,因为每个块中存储的记录数量是不等和变化的。在这种情况下,oracle计算每个数据块中记录数量的最大值,并根据这个最大值在位图中为每个数据块分配对应数量的标识位。而计算最大值的方法受hakan factor的影响。因此,如果我们减小hakan factor,便可以控制位图中为每个数据块分配的标识位数量,从而降低位图索引的占用空间,仅一步会降低位图逻辑操作时对内存的消耗。SQL> create table t1(c1 number);表已创建。SQL> insert into t1 values(1);已创建 1 行。SQL> /已创建 1 行。SQL> /已创建 1 行。SQL> alter table t1 minimize records_per_block;表已更改。SQL> create table t2 as select * from t1;表已创建。SQL> alter table t2 minimize records_per_block;表已更改。SQL> execute show_hakan('t1');Hakan factor for object 78156 (EASY.t1) is 2 with flags 8000PL/SQL 过程已成功完成。SQL> execute show_hakan('t2');Hakan factor for object 78157 (EASY.t2) is 2 with flags 8000PL/SQL 过程已成功完成。SQL> insert into t1 select * from t1;已创建 3 行。SQL> /已创建 6 行。SQL> /已创建 12 行。SQL> /已创建 24 行。SQL> /已创建 48 行。SQL> /已创建 96 行。SQL> /已创建 192 行。SQL> /已创建 384 行。SQL> /已创建 768 行。SQL> /已创建 1536 行。SQL> /已创建 3072 行。SQL> /已创建 6144 行。SQL> /已创建 12288 行。SQL> /已创建 24576 行。SQL> truncate table t2;表被截断。SQL> insert into t2 select * from t1;已创建 49152 行。SQL> commit;提交完成。 select ct, count(*) from ( Select Dbms_Rowid.Rowid_Block_Number(Rowid), Count(*) Ct from t1 group by dbms_rowid.rowid_block_number(rowid) ) Group By Ct 10 order by ct 11 / CT COUNT(*)---------- ---------- 3 16384 select ct, count(*) from ( Select Dbms_Rowid.Rowid_Block_Number(Rowid), Count(*) Ct from t2 group by dbms_rowid.rowid_block_number(rowid) ) Group By Ct 10 order by ct 11 / CT COUNT(*)---------- ---------- 3 16384SQL> alter table t1 nominimize records_per_block;表已更改。SQL> insert /*+append*/ into t1 select * from t1 where rownum<64;已创建 63 行。SQL> commit;提交完成。SQL> alter table t1 minimize records_per_block;表已更改。SQL> execute show_hakan('t1');Hakan factor for object 78156 (EASY.t1) is 62 with flags 8000PL/SQL 过程已成功完成。select ct, count(*) from ( Select Dbms_Rowid.Rowid_Block_Number(Rowid), Count(*) Ct from t1 group by dbms_rowid.rowid_block_number(rowid) ) Group By Ct 10 order by ct 11 / CT COUNT(*)---------- ---------- 3 16384 63 1SQL> create bitmap index i1 on t1(c1);索引已创建。SQL> create bitmap index i2 on t2(c1);索引已创建。SQL> select segment_name,blocks from user_segments where segment_name like 'I%';SEGMENT_NAME BLOCKS--------------------------------------------------------------------------------- ----------I1 16I2 8SQL> insert into t2 select * from t2 where rownum<64;已创建 63 行。SQL> commit;提交完成。SQL> select segment_name,blocks from user_segments where segment_name like 'I%';SEGMENT_NAME BLOCKS--------------------------------------------------------------------------------- ----------I1 16I2 8
>更多相关文章
首页推荐
佛山市东联科技有限公司一直秉承“一切以用户价值为依归
- 01-11全球最受赞誉公司揭晓:苹果连续九年第一
- 12-09罗伯特·莫里斯:让黑客真正变黑
- 12-09谁闯入了中国网络?揭秘美国绝密黑客小组TA
- 12-09警示:iOS6 惊现“闪退”BUG
- 11-18LG新能源宣布与Bear Robotics达成合作,成为
- 11-18机构:三季度全球个人智能音频设备市场强势
- 11-18闲鱼:注册用户过6亿 AI技术已应用于闲置交
- 11-18美柚、宝宝树回应“涉黄短信骚扰”:未发现
- 11-01京东七鲜与前置仓完成融合
相关文章
24小时热门资讯
24小时回复排行
热门推荐
最新资讯
操作系统
黑客防御