[20140813关于Hakan factor.txt

[20140813关于Hakan factor.txt

--曾经写过一篇通过执行ALTER TABLE MINIMIZE RECORDS_PER_BLOCK避免行迁移的blog.
http://blog.itpub.net/267265/viewspace-763315/

--里面的Hakan factor主要用来唯一映射表上行在位图索引.可以表示表的单个数据块的最大行数.
--记录在sys.tab$的spare1里面.

--昨天我查看随机安装的example例子发现一个奇怪的情况.自己也做一些测试.

@ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

show parameter db_block_size

NAME                                 TYPE                                     VALUE
------------------------------------ ---------------------------------------- -------
db_block_size                        integer                                  8192

SELECT a.owner,
       a.object_name,
       a.SUBOBJECT_NAME,
       a.object_id,
       a.data_object_id,
       a.object_type,
       b.spare1
  FROM dba_objects a, sys.tab$ b
WHERE a.object_id = b.obj# --AND A.DATA_OBJECT_ID = b.dataobj#
       AND a.owner = 'SH' AND a.object_type = 'TABLE';

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
SH     SALES                                          74088                TABLE                   149472
SH     COSTS                                          74117                TABLE                   151322
SH     TIMES                                          74146          73677 TABLE                       58
SH     PRODUCTS                                       74148          73678 TABLE                      219
SH     CHANNELS                                       74152          73679 TABLE                      579
SH     PROMOTIONS                                     74154          73680 TABLE                      225
SH     CUSTOMERS                                      74156          73681 TABLE                      225
SH     COUNTRIES                                      74158          73682 TABLE                      386
SH     SUPPLEMENTARY_DEMOGRAPHICS                     74160          73683 TABLE                      736
SH     CAL_MONTH_SALES_MV                             74161          73919 TABLE                      736
SH     FWEEK_PSCAT_SALES_MV                           74162          73920 TABLE                      476
SH     DR$SUP_TEXT_IDX$I                              74371          73837 TABLE                        0
SH     DR$SUP_TEXT_IDX$K                              74375                TABLE                        0
SH     DR$SUP_TEXT_IDX$R                              74377          73842 TABLE                        0
SH     DR$SUP_TEXT_IDX$N                              74380                TABLE                        0
SH     DIMENSION_EXCEPTIONS                           74541          74541 TABLE                      623
SH     SALES_TRANSACTIONS_EXT                         74549                TABLE                      736
SH     MY_STAT_TAB                                    96509          96509 TABLE                      736

18 rows selected.

-- 出了几个表SALES_TRANSACTIONS_EXT,MY_STAT_TAB,FWEEK_PSCAT_SALES_MV,CAL_MONTH_SALES_MV是736以外,其他都是奇怪的数值.
--其中sales,COSTS是分区表. 如果执行了ALTER TABLE MINIMIZE RECORDS_PER_BLOCK后我记得spare1=32768+最大行数-1.

SELECT a.owner,
       a.object_name,
       a.SUBOBJECT_NAME,
       a.object_id,
       a.data_object_id,
       a.object_type,
       b.spare1
  FROM dba_objects a, sys.tab$ b
WHERE a.object_id = b.obj# --AND A.DATA_OBJECT_ID = b.dataobj#
       AND a.owner = 'OE' AND a.object_type = 'TABLE';

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
OE     ORDERS                                         73990          73363 TABLE                      736
OE     INVENTORIES                                    73995          73365 TABLE                      736
OE     PRODUCT_INFORMATION                            73998          73367 TABLE                      736
OE     PRODUCT_DESCRIPTIONS                           74001          73369 TABLE                      736
OE     PROMOTIONS                                     74004          73371 TABLE                      736
OE     CUSTOMERS                                      73967          73345 TABLE                      736
OE     WAREHOUSES                                     73976          73351 TABLE                      736
OE     ORDER_ITEMS                                    73985          73359 TABLE                      736
OE     PURCHASEORDER                                  74465          74465 TABLE                      736
OE     LINEITEM_TABLE                                 74470          74470 TABLE                      736
OE     ACTION_TABLE                                   74466          74466 TABLE                      736
OE     CATEGORIES_TAB                                 74515          74515 TABLE                      736
OE     PRODUCT_REF_LIST_NESTEDTAB                     74516          74516 TABLE                      736
OE     SUBCATEGORY_REF_LIST_NESTEDTAB                 74518          74518 TABLE                      736
OE     ORDERS2                                        87152                TABLE                      736

15 rows selected.

--而oe模式下的例子都是736.手工建立一张表看看.

create table t1 (id number,name char(70));
SELECT a.owner,
       a.object_name,
       a.SUBOBJECT_NAME,
       a.object_id,
       a.data_object_id,
       a.object_type,
       b.spare1
  FROM dba_objects a, sys.tab$ b
WHERE a.object_id = b.obj# --AND A.DATA_OBJECT_ID = b.dataobj#
       AND a.owner = user AND a.object_type = 'TABLE'
       and a.object_name='T1';

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
SCOTT  T1                                            289651         289651 TABLE                      736

drop table t1 purge;
create table t1 (id number not null ,name char(70) not null);

--执行以上命令,不在重复写了.

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
SCOTT  T1                                            289652         289652 TABLE                      108

--简单推断: 数据块减去pctfree留下的10,  8192*.9/70=105.32. 相近不知道具体的算法???

drop table t1 purge;
create table t1 (id number ,name char(70) not null);

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
SCOTT  T1                                            289653         289653 TABLE                      109

drop table t1 purge;
create table t1 (id number not null ,name char(70) );

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
SCOTT  T1                                            289654         289654 TABLE                      736

--单单一个字段非空可能计算比736大.多加几个字段看看.
drop table t1 purge;
create table t1 (id1 number not null ,id2 number not null,id3 number not null,id4 number not null,id5 number not null,id6 number not null,id7 number not null,name char(70) );

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ -------------------- ---------- ---------- -------------- ------------------- ----------
SCOTT  T1                                  289658         289658 TABLE                      506

--很明显如果表T1定义存在一个是非空字段,并且占用一定的空间,建表是就会计算每个块spare1,如果比736大,等于736,如果小于736,等于该值.(注:736应该跟数据块大小有关)

--但是分区表的spare1又是如何计算的呢?无论安装以前的理解都不会是151322.

OWNER  OBJECT_NAME                    SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ ------------------------------ ---------- ---------- -------------- ------------------- ----------
SH     SALES                                          74088                TABLE                   149472
SH     COSTS                                          74117                TABLE                   151322

--抽取sh.costs的定义:
CREATE TABLE COSTS
(
  PROD_ID     NUMBER                            NOT NULL,
  TIME_ID     DATE                              NOT NULL,
  PROMO_ID    NUMBER                            NOT NULL,
  CHANNEL_ID  NUMBER                            NOT NULL,
  UNIT_COST   NUMBER(10,2)                      NOT NULL,
  UNIT_PRICE  NUMBER(10,2)                      NOT NULL
)
PARTITION BY RANGE (TIME_ID)

  PARTITION COSTS_1995 VALUES LESS THAN (TO_DATE(' 1996-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_1996 VALUES LESS THAN (TO_DATE(' 1997-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_H1_1997 VALUES LESS THAN (TO_DATE(' 1997-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_H2_1997 VALUES LESS THAN (TO_DATE(' 1998-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q1_1998 VALUES LESS THAN (TO_DATE(' 1998-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q2_1998 VALUES LESS THAN (TO_DATE(' 1998-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q3_1998 VALUES LESS THAN (TO_DATE(' 1998-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q4_1998 VALUES LESS THAN (TO_DATE(' 1999-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q1_1999 VALUES LESS THAN (TO_DATE(' 1999-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q2_1999 VALUES LESS THAN (TO_DATE(' 1999-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q3_1999 VALUES LESS THAN (TO_DATE(' 1999-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q4_1999 VALUES LESS THAN (TO_DATE(' 2000-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q1_2000 VALUES LESS THAN (TO_DATE(' 2000-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q2_2000 VALUES LESS THAN (TO_DATE(' 2000-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q3_2000 VALUES LESS THAN (TO_DATE(' 2000-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q4_2000 VALUES LESS THAN (TO_DATE(' 2001-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q1_2001 VALUES LESS THAN (TO_DATE(' 2001-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q2_2001 VALUES LESS THAN (TO_DATE(' 2001-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q3_2001 VALUES LESS THAN (TO_DATE(' 2001-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q4_2001 VALUES LESS THAN (TO_DATE(' 2002-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q1_2002 VALUES LESS THAN (TO_DATE(' 2002-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q2_2002 VALUES LESS THAN (TO_DATE(' 2002-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q3_2002 VALUES LESS THAN (TO_DATE(' 2002-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q4_2002 VALUES LESS THAN (TO_DATE(' 2003-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q1_2003 VALUES LESS THAN (TO_DATE(' 2003-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q2_2003 VALUES LESS THAN (TO_DATE(' 2003-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q3_2003 VALUES LESS THAN (TO_DATE(' 2003-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
  PARTITION COSTS_Q4_2003 VALUES LESS THAN (TO_DATE(' 2004-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
);

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ -------------------- ---------- ---------- -------------- ------------------- ----------
SCOTT  COSTS                               289718                TABLE                      405

--SPARE1=405 并不是149472.真不知道分区表如何计算的.仔细检查发现原表还建立了位图,重复执行+建立索引看看.

CREATE BITMAP INDEX COSTS_PROD_BIX ON COSTS (PROD_ID) LOCAL;
CREATE BITMAP INDEX COSTS_TIME_BIX ON COSTS (TIME_ID) LOCAL;

--还是一样.

--google找到如下链接:
http://dbaora.com/hakan-factor-ora-14642-ora-14643/

create table test_tbl
(
  id1 number   not null,
  id2 char(10) not null,
  id3 number
)
partition by range(id1)
(
  partition p1 values less than (10),
  partition p2 values less than (20)
);

create bitmap index test_tbl_idx1 on test_tbl(id1) local;

SELECT a.owner,
       a.object_name,
       a.SUBOBJECT_NAME,
       a.object_id,
       a.data_object_id,
       a.object_type,
       b.spare1
  FROM dba_objects a, sys.tab$ b
WHERE a.object_id = b.obj# --AND A.DATA_OBJECT_ID = b.dataobj#
       AND a.owner = user AND a.object_type = 'TABLE'
       and a.object_name='TEST_TBL';

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ -------------------- ---------- ---------- -------------- ------------------- ----------
SCOTT  TEST_TBL                            289898                TABLE                      540

alter table test_tbl drop column id3;
alter table test_tbl add(id3 number not null);

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ -------------------- ---------- ---------- -------------- ------------------- ----------
SCOTT  TEST_TBL                            289898                TABLE                    66076

--可以发现spare1出现巨大变化540=>66076.why?
--重复测试,建表后不建立位图索引,就没有这个问题.

drop table test_tbl purge ;
create table test_tbl
(
  id1 number   not null,
  id2 char(10) not null,
  id3 number
)
partition by range(id1)
(
  partition p1 values less than (10),
  partition p2 values less than (20)
);

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ -------------------- ---------- ---------- -------------- ------------------- ----------
SCOTT  TEST_TBL                            289904                TABLE                      540

alter table test_tbl drop column id3;
alter table test_tbl add(id3 number not null);

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE             SPARE1
------ -------------------- ---------- ---------- -------------- ------------------- ----------
SCOTT  TEST_TBL                            289904                TABLE                      476

--bug?还是表示什么不清楚,blog还演示了exchange partition的错误ORA-14642, ORA-14643.不知那位知道这些信息.

时间: 2024-10-23 10:27:30

[20140813关于Hakan factor.txt的相关文章

[20150720]为什么8K数据块Hakan Factor=736

[20150720]为什么8K数据块Hakan Factor=736.txt --前几天被别人问及这个问题,还真不好回答. --仔细思考,我觉得与行迁移有关,行迁移发生时,rowid不会变化.数据信息被移动另外的块,在块内保留一个指针. --也就是讲最小这条记录仅仅包含一个rowid指针. --还是通过例子来说明情况: 1.建立测试环境: SCOTT@test> @&r/ver1 PORT_STRING                    VERSION        BANNER ---

[20130809]12c Clustering Factor.txt

[20130809]12c Clustering Factor.txt 以前在11G以前,如果使用assm,表的CF经常会很大,即使你插入的像顺序号这样的字段,由于多个会话同时操作,插入的数据分布的不同的块中,以顺序号为索引的CF也会变得很大,甚至接近记录的数量.这个在<基于成本的优化>里面也有介绍. 但是在12g可以设置一个参数改善这种情况,做一些测试看看. 参考了Richard Foote大师的blog:http://richardfoote.wordpress.com/2013/05/0

[20150204]关于位图索引5.txt

[20150204]关于位图索引5.txt --许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是: 字段0:键值 字段1:开始rowid 字段2:结束rowid 字段3:位图信息,指示那行记录,位图1=>表示存在.位图0=>表示不存在. --但是字段4的位图信息,介绍的资料太少,我自己看了链接http://juliandyke.com/Presentations/BitmapIndexInternals.ppt,做一个简单探究. --前面的讲解仅仅在1个数据块的情况,如果开

[20160806]ROWDEPENDENCIES.txt

[20160806]ROWDEPENDENCIES.txt ---今天看一些文档,突然想起几天前做的行迁移与itl槽的测试: http://blog.itpub.net/267265/viewspace-2122712/ [20150720]为什么8K数据块Hakan Factor=736 http://blog.itpub.net/267265/viewspace-1742243/ --大家知道oracle如果一块发生dml操作,有1个伪列ora_rowscn记录最后的scn,但是不能通过这个

[20160803]另类行迁移.txt

[20160803]另类行迁移.txt --前几天做测试时,链接: http://blog.itpub.net/267265/viewspace-2122712/=>[20160729]行链接行迁移与ITL槽4.txt --发现一个块中的记录在字段长度变长后全部发生行迁移,感觉很奇怪,当时也没有仔细思考(开始以为至少有一些记录不会发生行迁移的 --情况),事后才想起来以前我做过类似的测试,参考链接: http://blog.itpub.net/267265/viewspace-1742243/=

[20150204]关于位图索引4.txt

[20150204]关于位图索引4.txt --许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是: 字段0:键值 字段1:开始rowid 字段2:结束rowid 字段3:位图信息,指示那行记录,位图1=>表示存在.位图0=>表示不存在. --但是字段4的位图信息,介绍的资料太少,我自己看了链接http://juliandyke.com/Presentations/BitmapIndexInternals.ppt,做一个简单探究. --前面的讲解仅仅在1个数据块的情况,如果开

[20121019]8k数据块到底能放多少行记录.txt

[20121019]8k数据块到底能放多少行记录.txt 前一阵子聚会,被问及一个8k数据块能够放多少行记录,我记得以前piner的书提高过,73X条. 实际上表sys.tab$的spare1字段保存的Hakan Factor,即该表数据块的最大行号,各种数据块的大小不同, spare1的缺省值也不一样. _______________________________ 块大小  最大行数每块(spare1)   _______________________________ 2K      17

[20130909]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED.txt

[20130909]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED.txt 在写[20130809]12c Clustering Factor.txt,链接 提到执行计划里面存在TABLE ACCESS BY INDEX ROWID BATCHED,这里的BATCHED表示什么? 自己不是很清楚. 既然多了一个batched,一定与原来的不同,具体含义是什么呢?做一些简单的探究: 1.建立测试环境: SCOTT@test01p> @ver BANNER  

[20150721]enq TX - allocate ITL entry

[20150721]enq TX - allocate ITL entry.txt --昨天我做了一个测试链接: http://blog.itpub.net/267265/viewspace-1742243/ --本想通过这个例子说明为什么8K数据块Hakan Factor=736? --晚上我想到一种这种特殊的表会不会产生enq TX - allocate ITL entry,也就是itl不足的情况. 1.建立测试环境: SCOTT@test> @ &r/ver1 PORT_STRING