oracle实验记录 (ROW 压缩,迁移,链接)

Row Chaining &Row Migrating 定义

Row chaining:当数据第一次insert到一个块时就无法容纳,此时将发生row chaining,将放在多个块中由指针链接(用rowid链接)

ROW migrating:当一个块内数据 由于update更新操作导致,长度变大,原来的块放不下了,oracle将进行row migrating,将在原来的块中保存一个指针,指向新的datablock(但迁移行的rowid不变,通过rowid可以查到FILE#,BLOCK#)

 

与之有关的建立表时的 参数 PCTFREE,PCTUSED(ASSM(auto segment space mangagement)表空间 中pctused已经废弃,因为assm tablespace 不用 freelist管理空间,而用BITMAP,而PCTUSED主要作用就是告诉oracle什么时候 块要挂到freelist,没有 freelist了 所以pctused也废弃了,不过pctfree还有作用 还限制新行能否插入一个块中

PCTFREE:指定表内每个数据块中空间的百分比。PCTFREE 的值必须介于0 和99
之间。如果值为零,表示可以通过插入新行来填充整个块。缺省值为10。此值表示每
个块中保留着10% 的空间,用于更新现有的行以及插入新行,每个块最多可填充到
90%。
PCTUSED:指定为表内每个数据块维护的已用空间的最小百分比。如果一个块的已用
空间低于PCTUSED,则可在该块中插入行。PCTUSED 的值为介于0 和99 之间的整
数,缺省值为40。(segment management space manual时候 控制块是否在FREELIST上),pctfree加pctused要小于100
 


小结:总得来说PCTFREE 就是告诉ORACLE 什么时候把BLOCK从FREELIST拿走(自动段空间管理没有FREELIST)拿走后,当空闲空间=pctfree时候 将不允许插入新数据,然后随着使用即使以后的空闲空间>PCTFREE 块也不挂到FREELIST(使用空间<90%时),只有当已使用空间

 


由于是1OGR2 默认表空间都是ASSM 简单实验下pctfree对row chaining的影响

 

SQL> sho user
USER 为 "XH"
SQL>
SQL> create table t1 (a char(2000), b char(2000), c char(2000), d char(2000));建立一个表

表已创建。

SQL> insert into t1 values('a','b','c','d');~~插入大数据

已创建 1 行。
SQL> show parameter block_size

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

SQL> select pct_free from user_tables where table_name='T1';

  PCT_FREE
----------
        10

可以看 到default pctfree为10,块大小为8192,还要留10%用于更新 ,块头信息+行数据区信息 应该<90%才能都放入这个块,而实验中每个字段为 2000字节,90%空间放不下数据行,将造成row chaining


SQL> ANALYZE TABLE t1 LIST CHAINED ROWS;oracle分析表 如果有row chaining or row migrate 那么将会放入chained_rows这个表


表已分析。

chained_rows表需要建立
  脚本 位置 :RDBMS\ADMIN\utlchain.sql;

Table created. 生成CHAINED_ROWS
create table CHAINED_ROWS (
  owner_name         varchar2(30),
  table_name         varchar2(30),
  cluster_name       varchar2(30),
  partition_name     varchar2(30),
  subpartition_name  varchar2(30),
  head_rowid         rowid,
  analyze_timestamp  date
);


SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

TABLE_NAME                       COUNT(*)
------------------------------ ----------
T1                                      1~~~~看到有一个row chaining

 

SQL> ANALYZE TABLE T1 COMPUTE STATISTICS;~~~另外直接用analyze也可以分析统计出来

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='T1' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         1          1~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

SQL> create table t2 (a char(2000), b char(2000), c char(2000), d char(2000)) pc
tfree 0;

表已创建。

SQL> select pct_free from user_tables where table_name='T2';

  PCT_FREE
----------
         0
建立另外一个表 T2 PCTFREE设置为0 没有留update空间,行数据区+块头信息 可以使用块的100%空间

 

 

 

SQL> insert into t2 values('a','b','c','d');

已创建 1 行。

SQL> commit;

提交完成。

SQL> ANALYZE TABLE T2 COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='T2' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         1          0~~~~~~~~~~没有产生row chainging

SQL> ANALYZE TABLE t2 LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

TABLE_NAME                       COUNT(*)
------------------------------ ----------
T1                                      1~~~~~~~~~~没有表T2的信息

 row chaining 的解决
降低PCT FREE

SQL> alter table t1 pctfree 0;

表已更改。

 

用10046 跟踪move操作过程
看 到内部相当于 一个 ctas操作
SQL> alter session set events '10046 trace name context forever,level 12';

会话已更改。

SQL> alter table t1 move;

表已更改。
trace中 摘录内容:

WAIT #3: nam='direct path write' ela= 3 file number=4 first dba=2444 block cnt=13 obj#=0 tim=325785989
WAIT #3: nam='direct path write' ela= 49 file number=4 first dba=2444 block cnt=13 obj#=0 tim=325786033
WAIT #3: nam='direct path write' ela= 2 file number=4 first dba=2458 block cnt=5 obj#=0 tim=325786070
WAIT #3: nam='direct path write' ela= 3 file number=4 first dba=2458 block cnt=5 obj#=0 tim=325786418
WAIT #3: nam='direct path write' ela= 59 file number=4 first dba=2458 block cnt=5 obj#=0 tim=325786474
看到大量的 直接路径插入 实验 表


更新数据字典操作
delete from seg$ where ts#=:1 and file#=:2 and block#=:3

insert into seg$ (file#,block#,type#,ts#,blocks,extents,minexts,maxexts,extsize,extpct,user#,iniexts,lists,groups,cachehint,bitmapranges,hwmincr, spare1, scanhint) values

.....................

SQL> alter session set events '10046 trace name context off';

会话已更改。

 

SQL> ANALYZE TABLE T1 COMPUTE STATISTICS;~~~

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='T1' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         1          0

消除了row chaining~~~~另外MOVE 由于是重新insert这样造成rowid改变所以index的失效,move还会锁表

 

SQL> create table tm ( a int);

表已创建。

SQL> insert into tm values(1);

已创建 1 行。

SQL> commit;

提交完成。

SQL> create index tm_ind on tm(a);


SQL> select STATUS from user_indexes where index_name='TM_IND';

STATUS
--------
VALID~~~~~~~~~~~~INDEX 失效

SQL> alter table TM MOVE;

表已更改。

SQL> select STATUS from user_indexes where index_name='TM_IND';

STATUS
--------
UNUSABLE

 

SQL> alter index  tm_ind rebuild online ;

索引已更改。

SQL>

 

 

另外一种方式,row chaining出现的根本原因就是INSERT时候块太小,所以 要建立大块的表空间,下面是早期实验中此类方法的解决


SQL> create table test2(a char(2000),b char(2000),c char(2000),d char(2000),e ch
ar(2000)) tablespace test;

Table created.

SQL> insert into test2 values('a','aa','aaa','aaaa','aaaaa');

1 row created.
commit;


SQL> select segment_name,file_id,block_id,blocks from dba_extents where segment_
name='TEST2' and wner='XH';

SEGMENT_NAME            FILE_ID   BLOCK_ID     BLOCKS
-------------------- ---------- ---------- ----------
TEST2                        10         33          8

 


SQL> alter system dump datafile 10 block min 34 block max 42;

System altered.
转储一下数据块的结构

buffer tsn: 20 rdba: 0x02800022 (10/34)
block_row_dump:
tab 0, row 0, @0x69
tl: 7967 fb: -----LP- lb: 0x1  cc: 4(4列)
col  0: [1952]
........................
buffer tsn: 20 rdba: 0x02800023 (10/35)
tab 0, row 0, @0x1793
tl: 2061 fb: --H-F--N lb: 0x1  cc: 2(2列)
nrid:  0x02800022.0***** 用rowid连接
col  0: [2000]
~~~~~~~~~~~~~~~~~~~~~~~~~~6列分到2个block中

H-表示当前数据块是该行的第一个块(不一定包含该行的数据,如row migrate)
F-表示该行数据的第一个片断
L-表示改行的最后一个片断
FL-表示改行的数据都在该数据快中.
N-表示该行在当前这个数据块中的最后一列没有结束,其余的数据存放在由rowid指向的下一个数据块中 (next表示这一行连接到下一行)。
P-表示该行在当前这个数据块中的第一列是从别的块延续过来的。
PN-会出现在行chained的地方,如果一行的数据超过一个块时就会出现

SQL> ANALYZE TABLE TEST2 COMPUTE STATISTICS;

Table analyzed.
计算下row migregate or row链接数量


SQL> select num_rows,chain_cnt from dba_tables where table_name='TEST2' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         1          1 ~~~~~~有一个行链接

 

SQL> @E:\oracle\product\10.1.0\Db_1\RDBMS\ADMIN\utlchain.sql;

Table created. 生成CHAINED_ROWS
create table CHAINED_ROWS (
  owner_name         varchar2(30),
  table_name         varchar2(30),
  cluster_name       varchar2(30),
  partition_name     varchar2(30),
  subpartition_name  varchar2(30),
  head_rowid         rowid,~~*************************
  analyze_timestamp  date
);

 SQL> ANALYZE TABLE test2 LIST CHAINED ROWS; 会放入 chained_rows

Table analyzed.
SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

TABLE_NAME                       COUNT(*)
------------------------------ ----------
TEST2                                   1
SQL> SELECT name, value FROM v$sysstat WHERE name = 'table fetch continued row'
  2  ;

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                               164

查询系统中存在 row 链接的数量
SQL> SELECT  head_rowid from chained_rows;~

HEAD_ROWID
------------------
AAANORAAKAAAAAjAAA

SQL> select rowid from test2;

ROWID
------------------
AAANORAAKAAAAAjAAA

~2个能得到当前 链接or migrate的数量

row链接 清除 move exp/imp不管用 ~因为本身这行太长 其他块一样放不下,所以 只能加db_block_size清除


SQL> alter system set db_16k_cache_size=2m;

System altered.


SQL> show parameter db_16

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_16k_cache_size                    big integer 8M  ~~~~~granule

on 32-bit Windows NT, the granule size is 8 MB for SGAs larger than 128 MB  9I
on 32-bit Windows, the granule size is 8 M for SGAs larger than 1 GB.     10G
受 _ksmg_granule_size控制

Enter value for par: ksmg_granule_size
old  14:   x.ksppinm like '%_&par%'
new  14:   x.ksppinm like '%_ksmg_granule_size%'

NAME                           VALUE                     ISDEFAULT ISMOD      IS
ADJ
------------------------------ ------------------------- --------- ---------- --
---
KSPPDESC
--------------------------------------------------------------------------------
----------------------------------------------------
_ksmg_granule_size             4194304                   TRUE      FALSE      FA
LSE
granule size in bytes

 

 


SQL> create tablespace test_16KB datafile 'd:\test_16KB.dbf' size 10m blocksize
16k;

Tablespace created.

 

SQL> alter table xh.test2 move  tablespace test_16kb;

Table altered.

SQL>
SQL> ANALYZE TABLE test2 LIST CHAINED ROWS;

Table analyzed.

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

no rows selected


SQL> ANALYZE TABLE TEST2 COMPUTE STATISTICS;

Table analyzed.

SQL> select num_rows,chain_cnt from dba_tables where table_name='TEST2';

  NUM_ROWS  CHAIN_CNT
---------- ----------
         1          0****************************
SQL> truncate table chained_rows;

Table truncated.

SQL> ANALYZE TABLE test2 LIST CHAINED ROWS;

Table analyzed.

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

no rows selected~~~~~~~~~~~~~~~~~~~~~~~~消除了

 

 

 

ROW migrate


SQL> create table migrate (a char(2000), b char(2000),c char(2000));

表已创建。

SQL> insert into migrate(a,b) values('a','a');

已创建 1 行。

SQL> insert into migrate(a) values('b');

已创建 1 行。

SQL> commit;

提交完成。

SQL> select segment_name,file_id,block_id,blocks from dba_extents where segment_
name='MIGRATE' and wner='XH';

SEGMENT_NAME                      FILE_ID   BLOCK_ID     BLOCKS
------------------------------ ---------- ---------- ----------
MIGRATE                                 4       3681          8

 

SQL> select file#,block# ,rowid from (select dbms_rowid.rowid_relative_fno(rowid
) file#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from MIGRATE);

     FILE#     BLOCK# ROWID
---------- ---------- ------------------
         4       3685 AAANSQAAEAAAA5lAAA
         4       3685 AAANSQAAEAAAA5lAAB

SQL>

 

SQL> ANALYZE TABLE migrate LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

未选定行


SQL> ANALYZE TABLE MIGRATE COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          0

分析 现在有2行 没有row migrate

SQL> alter system dump datafile 4 block 3685;

系统已更改。


data_block_dump,data header at 0x8062264
===============
tsiz: 0x1f98
hsiz: 0x16
pbl: 0x08062264
bdba: 0x01000e65
     76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x819
avsp=0x803
tosp=0x803
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0xfef
0x14:pri[1] offs=0x819
block_row_dump:
tab 0, row 0, @0xfef
tl: 4009 fb: --H-FL-- lb: 0x1  cc: 2 (第1行中2列)
col  0: [2000]
 61 20 20 20 20 20 20 2~~~~~~~~~~~~~~~值A
col  1: [2000]
 61 20 20 20 ~~~~~~~~~~~~~~~~~~~~~~~~值A
tl: 2006 fb: --H-FL-- lb: 0x1  cc: 1(第2行中2列)
col  0: [2000]
 62 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 20 20 20 20 20 ~~~~~~~~~~~~~~~~~~~~~~~值B

 

H-FL的意思:


H-表示当前数据块是该行的第一个块
FL-表示改行的数据都在该数据快中

上边trace文件可以看出 2行都 存在该块中

 

SQL> ANALYZE TABLE migrate LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

TABLE_NAME                       COUNT(*)
------------------------------ ----------
MIGRATE                                 1

SQL> ANALYZE TABLE MIGRATE COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          1

SQL> select file#,block# ,rowid from (select dbms_rowid.rowid_relative_fno(rowid
) file#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from MIGRATE);

     FILE#     BLOCK# ROWID
---------- ---------- ------------------
         4       3685 AAANSQAAEAAAA5lAAA
         4       3685 AAANSQAAEAAAA5lAAB~~~rowid没变

 

 

SQL> alter system dump datafile 4 block 3685;

系统已更改。


flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x819
avsp=0x803
tosp=0xfd0
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0xfef
0x14:pri[1] offs=0x819
block_row_dump:
tab 0, row 0, @0xfef
tl: 4009 fb: --H-FL-- lb: 0x0  cc: 2(2列)


col  0: [2000]
 61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 20 20 20 20 20

 

col  1: [2000]
 61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 20 20 20 20 2

-H-FL-- 可以看到 这行 头和尾都在一个块中
tl: 9 fb: --H----- lb: 0x2  cc: 0~~~~~~~(0列 原来的 数据迁移了)
nrid:  0x01000e66.0~~~指针指向迁移的block,ROWID不变,可以从H 看出来 表示当前数据块是该行的第一个块(不一定包含该行的数据,如row migrate)
end_of_block_dump

 


通过NRID 找到 迁移行所在的block

SQL> variable file# number;
SQL> variable blk# number;
SQL> execute :file#:=dbms_utility.data_block_address_file(to_number('1000e66','x
xxxxxx'));

PL/SQL 过程已成功完成。

SQL>  execute :blk#:=dbms_utility.data_block_address_block(to_number('1000e66','
xxxxxxx'));

PL/SQL 过程已成功完成。

SQL> print file#

     FILE#
----------
         4

SQL> print blk#

      BLK#
----------
      3686

 

 

SQL> alter system dump datafile 4 block 3686;

系统已更改。


flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x7fe
avsp=0x7ea
tosp=0x7ea
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x7fe
block_row_dump:
tab 0, row 0, @0x7fe
tl: 6018 fb: ----FL-- lb: 0x1  cc: 3(3列)
hrid: 0x01000e65.1*****这个HRID 也是一个指针 指向原来迁移的位置的块

col  0: [2000]
 62 20 20 20 ~~~~值B
col  1: [2000]
 62 20 20 20~~~~值B
col  2: [2000]
 62 20 20 20~~~~值B


通过hrid找到原来迁移前所在的block


SQL> variable blk# number;
SQL> variable file# number;
SQL> execute :file#:=dbms_utility.data_block_address_file(to_number('1000e65','x
xxxxxx'));

PL/SQL 过程已成功完成。

SQL>  execute :blk#:=dbms_utility.data_block_address_block(to_number('1000e65','
xxxxxxx'));

PL/SQL 过程已成功完成。

SQL> print file#

     FILE#
----------
         4

SQL> print blk#

      BLK#
----------
      3685

可以看出正是 迁移前所在的位置

 

 

关于消除row migrate 有很多种方法

1.MOVE 方法


SQL> ANALYZE TABLE migrate LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

未选定行

SQL> ANALYZE TABLE MIGRATE COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          0

消除了 (注意move 会让index失效,而且 LOCK表)

 

2.EXP/IMP 方法


SQL> create table migrate2 (a char(2000), b char(2000),c char(2000));

表已创建。

SQL> insert into migrate2(a,b) values('a','a');

已创建 1 行。

SQL> insert into migrate2(a) values('b');

已创建 1 行。

SQL> commit;

提交完成。

SQL> update migrate2 set b='b',c='b' where a='b';

已更新 1 行。

SQL> commit;

提交完成。

SQL> ANALYZE TABLE migrate2 LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

TABLE_NAME                       COUNT(*)
------------------------------ ----------
MIGRATE2                                1

SQL> ANALYZE TABLE MIGRATE2 COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE2' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          1

C:\>mkdir e:\exp

C:\>exp xh/a831115 file=e:\exp\migrate2.dmp tables=migrate2

Export: Release 10.2.0.1.0 - Production on 星期六 10月 24 23:58:38 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集

即将导出指定的表通过常规路径...
. . 正在导出表                        MIGRATE2导出了           2 行
成功终止导出, 没有出现警告。

 

 

SQL> truncate table migrate2;

表被截断。
C:\>imp xh/a831115 file=e:\exp\migrate2.dmp tables=migrate2 ignore=y

Import: Release 10.2.0.1.0 - Production on 星期日 10月 25 00:05:16 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

经由常规路径由 EXPORT:V10.02.01 创建的导出文件
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
. 正在将 XH 的对象导入到 XH
. 正在将 XH 的对象导入到 XH
. . 正在导入表                      "MIGRATE2"导入了           2 行
成功终止导入, 没有出现警告。

 

SQL> ANALYZE TABLE MIGRATE2 COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE2' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          0

SQL> truncate table chained_rows;

表被截断。

SQL> ANALYZE TABLE migrate LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

未选定行

SQL>
消除了

 

3.CTAS 方式

CREATE TABLE table_name_temp AS SELECT * FROM table_name WHERE rowid IN(SELECT head_rowid FROM chained_rows WHERE table_name = 'table_name');
DELETE table_name WHERE rowid IN(SELECT head_rowidFROM chained_rowsWHERE table_name = 'table_name');
INSERT INTO table_name SELECT * FROM table_name_temp;DROP TABLE table_name_temp;
很简单ctas重新建立一个表(直接加载写入)
将迁移行 复制到 新表中
从原始表删除迁移行
将行从新表复制到原表中


SQL> create table migrate3 (a char(2000), b char(2000),c char(2000));

表已创建。

SQL> insert into migrate3(a,b) values('a','a');

已创建 1 行。

SQL> insert into migrate3(a) values('b');

已创建 1 行。

SQL> commit;

提交完成。

SQL> update migrate3 set b='b',c='b' where a='b';

已更新 1 行。

SQL> commit;

提交完成。

SQL> ANALYZE TABLE migrate3 LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

TABLE_NAME                       COUNT(*)
------------------------------ ----------
MIGRATE3                                1

SQL> ANALYZE TABLE MIGRATE3 COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE3' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          1

 

SQL> create table migrate3_test as select * from migrate3 where rowid in (select
 head_rowid from chained_rows where table_name='MIGRATE3');

表已创建。

SQL> delete migrate3 where rowid in (select head_rowid from chained_rows where t
able_name='MIGRATE3');

已删除 1 行。

SQL> commit;

提交完成。

SQL> insert into migrate3 select * from MIGRATE3_TEST;

已创建 1 行。

SQL> commit
  2  ;

提交完成。


SQL> drop TABLE MIGRATE3_TEST;

表已删除。

SQL> ANALYZE TABLE MIGRATE3 COMPUTE STATISTICS;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='MIGRATE3' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
         2          0

SQL> TRUNCATE TABLE CHAINED_ROWS ;

表被截断。

SQL> ANALYZE TABLE migrate3 LIST CHAINED ROWS;

表已分析。

SQL> SELECT table_name, count(*) from chained_rows GROUP BY table_name;

未选定行

消除了

 

 

关于表压缩

 

oracle compress


可以压缩数据块内重复的值,重复值存在符号表(块头),原来位置存一个指针指向符号表

 

 

SQL> create table cm (a char(20),b char(20));

表已创建。

 


SQL> ed
已写入 file afiedt.buf

  1    declare
  2    begin
  3    for i in  1..1000 loop
  4    insert into cm values('a','b');
  5    end loop;
  6    for i in  1..1000 loop
  7    insert into cm values('a'||i,'b'||i);
  8    end loop;
  9   commit;
 10*  end;
 11  /

PL/SQL 过程已成功完成。

SQL>

SQL> select count(distinct a) from cm;

COUNT(DISTINCTA)
----------------
            1001

SQL> select count(distinct b) from cm;

COUNT(DISTINCTB)
----------------
            1001

SQL>
可以 看到这个表a,b列有1001个不同值


SQL> col segment_name format a10
SQL>  select segment_name,file_id,block_id,blocks from dba_extents where segment
_name='CM';

SEGMENT_NA    FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
CM                  4       2329          8
CM                  4       2353          8

SQL> select file_id,block_id,blocks from dba_extents where segment_name='CM';

   FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------
         4       2329          8
         4       2353          8

SQL> select distinct block#  from (select dbms_rowid.rowid_relative_fno(rowid) f
ile#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from CM);

    BLOCK#
----------
      2333
      2353
      2354
      2357
      2358
      2359
      2332
      2334
      2335
      2336
      2355

    BLOCK#
----------
      2356
      2360

已选择13行。

SQL>


SQL> alter table xh.cm move compress;

表已更改。


SQL>  select segment_name,file_id,block_id,blocks from dba_extents where segment
_name='CM';

SEGMENT_NA    FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
CM                  4       2361          8
CM                  4       2369          8

SQL> select file_id,block_id,blocks from dba_extents where segment_name='CM';

   FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------
         4       2361          8
         4       2369          8

SQL> select distinct block#  from (select dbms_rowid.rowid_relative_fno(rowid) f
ile#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from CM);

    BLOCK#
----------
      2364
      2367
      2368
      2369
      2371
      2365
      2366
      2370

已选择8行。
~~~~~~~~~~~~~~~~可以看到使用的 块减少了(13减少为8)


转储结构看下


SQL> alter system dump datafile 4 block 2364;

系统已更改。

data_block_dump,data header at 0x80c227c
===============
tsiz: 0x1f80 (total data area size)
hsiz: 0x5bc (data header size=(14+ntabs*4 + nrows*2)
pbl: 0x080c227c  (pointer to buffer holding the block)
bdba: 0x0100093c (block dba ,rdba)
     76543210
flag=-0------(O表示 compress , n=pctfree hit (clusters),f=don't put on freelist, k=flushable cluster keys)
ntab=2 (表示块中含有2个表信息,有一个就是symbol table,cluster时候也>1)
nrow=716  (number of rows)~~~可以看到如果是正常表,这个块是存不了 这么多行应该在200ROW左右
frre=-1 
fsbo=0x5bc (free space begin offset)
fseo=0x115c (free space end offset)
avsp=0x74 (available space in the block)
tosp=0x74(total available space when all transactions commit)
 r0_9ir2=0x0
 mec_kdbh9ir2=0x1
               76543210
 shcf_kdbh9ir2=----------
           76543210
 flag_9ir2=--R----C
  fcls_9ir2[3]={ 0 32768 32768 }
0x1c:pti[0] nrow=1 offs=0    (symbol表里有一条记录(a,b)存compress后的值)
0x20:pti[1] nrow=715 offs=1 这个block中其余 715条是重复记录只存指向symbol的指针
0x24:pri[0] offs=0x1f53
0x26:pri[1] offs=0x1f4e
0x28:pri[2] offs=0x1f49
''''''''''''''''''''''''''''''
0x5ba:pri[715] offs=0x115c
block_row_dump:
tab 0, row 0, @0x1f53 (tab 0 就是符号表)
tl: 45 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [20]  61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  值 A
col  1: [20]  62 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  值 B
bindmp: 02 cb 02 dc 61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 dc 62 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

tab 1, row 0, @0x1f4e
tl: 5 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [20]  61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20~~~值A
col  1: [20]  62 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20~~~值B
bindmp: 2c 00 01 02 00  (02 表示compress 2个字段)


.................................

tab 1, row 714, @0x115c
tl: 5 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [20]  61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
col  1: [20]  62 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
bindmp: 2c 00 01 02 00~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~指针指向符号表,存储的实际值,就是这样大量的指针指向符号表

 

 

关于compress与 row migrate

如果执行UPDATE 将造成row migrate 表变大.
SQL> analyze table cm compute statistics;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='CM' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
      2000          0


SQL> update cm set b='c';

已更新2000行。

SQL> commit;

提交完成。

SQL> analyze table cm compute statistics;

表已分析。

SQL> select num_rows,chain_cnt from dba_tables where table_name='CM' ;

  NUM_ROWS  CHAIN_CNT
---------- ----------
      2000        844

一个update操作产生大量row migrate


SQL> alter system dump datafile 4 block 2364;

系统已更改。

tl: 9 fb: --H----- lb: 0x2  cc: 0
nrid:  0x01000944.0~~~~~~~~~~~~~~~~~~~~~~~~~~~~ROW migrate 指向迁移到的block
bindmp: 20 02 00 01 00 09 44 00 00
tab 1, row 3, @0x1ee5
tl: 9 fb: --H----- lb: 0x2  cc: 0
nrid:  0x01000944.1
bindmp: 20 02 00 01 00 09 44 00 01
tab 1, row 4, @0x1edc
tl: 9 fb: --H----- lb: 0x2  cc: 0
nrid:  0x01000944.2


SQL> col segment_name format a10
SQL> select segment_name,file_id,block_id,blocks from dba_extents where segment_
name='CM';

SEGMENT_NA    FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
CM                  4       2361          8
CM                  4       2369          8
CM                  4       2409          8~~~~~~~~~~~~可以看到表变大了(原来是2个区,现在3个区)

 

 

 

 


 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12020513/viewspace-611339/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12020513/viewspace-611339/

你可能感兴趣的:(oracle实验记录 (ROW 压缩,迁移,链接))