[20150929]11g关于行链接.txt
--曾经写过block record flag:
http://blog.itpub.net/267265/viewspace-1753924/
http://blog.itpub.net/267265/viewspace-1753933/
--总结如下:
#define KDRHFK 0x80 Cluster Key =>使用K表示
#define KDRHFC 0x40 Clustered table member =>使用C表示
#define KDRHFH 0x20 Head piece of row =>使用H表示
#define KDRHFD 0x10 Deleted row =>使用D表示
#define KDRHFF 0x08 First data piece =>使用F表示
#define KDRHFL 0x04 Last data piece =>使用L表示
#define KDRHFP 0x02 First column continues from Previous piece =>使用P表示
#define KDRHFN 0x01 Last column continues in Next piece =>使用N表示
--提到
#define KDRHFP 0x02 First column continues from Previous piece
#define KDRHFN 0x01 Last column continues in Next piece
--最后2个表示在8k的数据块应该很难看到,不过问一下别人8i,9i好像看到过。
--实际上信息跨2个或者多个数据块,我演示使用2k的数据块。这样1个数据块放不下4000个字节的字段,才出现那2个flag。
--昨天被别人问及这个问题,不管怎样我在11g下没有看到这2个flag在8k的数据块的情况下出现,在11G下做一个例子:
1.建立环境:
SCOTT@test> @ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.3.0 Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
create table t ( id number,col1 varchar2(4000), col2 varchar2(4000), col3 varchar2(4000));
insert into t values (1,lpad('1', 4000, '1'), lpad('2', 4000, '2'), lpad('3', 4000, '3'));
commit ;
SCOTT@test> select rowid from t;
ROWID
------------------
AABNUUAAEAAAACkAAA
SCOTT@test> @rowid AABNUUAAEAAAACkAAA
OBJECT FILE BLOCK ROW DBA TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
316692 4 164 0 4,164 alter system dump datafile 4 block 164 ;
SCOTT@test> alter system checkpoint;
System altered.
2.使用bbed观察:
--注实际上使用转储也可以查看,我喜欢使用bbed观察,这样更加快以及直观一些。
BBED> set dba 4,164
DBA 0x010000a4 (16777380 4,164)
BBED> p *kdbr[0]
rowdata[0]
----------
ub1 rowdata[0] @4173 0x28
BBED> x /rnccc
rowdata[0] @4173
----------
flag@4173: 0x28 (KDRHFF, KDRHFH)
lock@4174: 0x01
cols@4175: 2
nrid@4176:0x010000a7.0
col 0[2] @4182: 1
col 1[4000] @4185: 1111111111111111111111111111111111111111111....
--继续看链接的数据块情况:
BBED> set dba 0x010000a7
DBA 0x010000a7 (16777383 4,167)
BBED> p *kdbr[0]
rowdata[0]
----------
ub1 rowdata[0] @4176 0x00
BBED> x /rccc
rowdata[0] @4176
----------
flag@4176: 0x00 (NONE)
lock@4177: 0x01
cols@4178: 1
nrid@4179:0x010000a3.0
col 0[4000] @4185: 2222222222222222222222222222222222222222222....
--继续看链接的数据块情况:
BBED> set dba 0x010000a3
DBA 0x010000a3 (16777379 4,163)
BBED> p *kdbr[0]
rowdata[0]
----------
ub1 rowdata[0] @4182 0x04
BBED> x /rccc
rowdata[0] @4182
----------
flag@4182: 0x04 (KDRHFL)
lock@4183: 0x01
cols@4184: 1
col 0[4000] @4185: 33333333333333333333333333333333333333333333333
-- 对照上面发现:
#define KDRHFK 0x80 Cluster Key =>使用K表示
#define KDRHFC 0x40 Clustered table member =>使用C表示
#define KDRHFH 0x20 Head piece of row =>使用H表示
#define KDRHFD 0x10 Deleted row =>使用D表示
#define KDRHFF 0x08 First data piece =>使用F表示
#define KDRHFL 0x04 Last data piece =>使用L表示
#define KDRHFP 0x02 First column continues from Previous piece =>使用P表示
#define KDRHFN 0x01 Last column continues in Next piece =>使用N表示
flag@4173: 0x28 (KDRHFF, KDRHFH) => dba 4,164 0x28 Head piece of row+First data piece
flag@4176: 0x00 (NONE) => dba 4,167 0x00
flag@4182: 0x04 (KDRHFL) => dba 4,163 0x04 Last data piece
--依旧没有看到
#define KDRHFP 0x02 First column continues from Previous piece
#define KDRHFN 0x01 Last column continues in Next piece
--很明显这3个字段colx分布在3个块,并且每个字段并没有被拆开。这样情况下通过索引访问逻辑读比一般的情况下多1到2个逻辑读。
3.建立索引测试:
SCOTT@test> create unique index pk_t on t(id);
Index created.
SCOTT@test> alter session set statistics_level=all;
Session altered.
SCOTT@test> select * from t where id=1;
...
SCOTT@test> @dpcz ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 07hpk6hpb7pp8, child number 0
-------------------------------------
select * from t where id=1
Plan hash value: 2454218153
------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 1 (100)| | 1 |00:00:00.01 | 4 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 6019 | 1 (0)| 00:00:01 | 1 |00:00:00.01 | 4 |
|* 2 | INDEX UNIQUE SCAN | PK_T | 1 | 1 | | 0 (0)| | 1 |00:00:00.01 | 1 |
------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T@SEL$1
2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=1)
25 rows selected.
4.继续通过例子来说明问题:
--建立表t1:
create table t1 ( id number,col1 varchar2(1000), col2 varchar2(1000), col3 varchar2(1000),col4 varchar2(1000));
insert into t1 select rownum ,lpad('1', 1000, '1'), lpad('2', 1000, '2'), lpad('3', 1000, '3'),lpad('4', 1000, '4') from dual connect by level<=100;
commit ;
SCOTT@test> select distinct substr(rowid,-3,3) from t1;
SUBSTR
------
AAA
--substr(rowid,-3,3)表示取rowid最后3个字符,可以发现都是'AAA',也就是行号都是0,也就是讲每块1条记录。
SCOTT@test> select rowid from t1 where rownum=1;
ROWID
------------------
AABNVqAAEAAAAIbAAA
SCOTT@test> @rowid AABNVqAAEAAAAIbAAA
OBJECT FILE BLOCK ROW DBA TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
316778 4 539 0 4,539 alter system dump datafile 4 block 539 ;
SCOTT@test> alter system checkpoint;
System altered.
BBED> set dba 4,539
DBA 0x0100021b (16777755 4,539)
BBED> map
File: /u01/app/oracle11g/oradata/test/users01.dbf (4)
Block: 539 Dba:0x0100021b
------------------------------------------------------------
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes @0
struct ktbbh, 72 bytes @20
struct kdbh, 14 bytes @100
struct kdbt[1], 4 bytes @114
sb2 kdbr[1] @118
ub1 freespace[4050] @120
ub1 rowdata[4018] @4170
ub4 tailchk @8188
--可以发现freespace=4050, 4050/8000=.50625,剩余接近50%的空间被浪费了。像这种情况最好使用更大的数据块,但是这样有带来管理
--上的麻烦,要合理设置参数,总之在数据库设计上注意这些问题,如果行接近4K的情况下,最好选择更大的数据块,合理设置参数避免
--空间的浪费.
--补充测试,如果设置pctfree=0:
create table t1 ( id number,col1 varchar2(1000), col2 varchar2(1000), col3 varchar2(1000),col4 varchar2(1000)) pctfree 0;
insert into t1 select rownum ,lpad('1', 1000, '1'), lpad('2', 1000, '2'), lpad('3', 1000, '3'),lpad('4', 1000, '4') from dual connect by level<=100;
commit ;
SCOTT@test> select count( substr(rowid,-3,3)),substr(rowid,-3,3) from t1 group by substr(rowid,-3,3);
COUNT(SUBSTR(ROWID,-3,3)) SUBSTR
------------------------- ------
50 AAA
50 AAB
--这样空间利用率最高,但是如果表存在一些dml(update的行变大的情况),会出现行迁移。总之注意这些细节。