Clustering table 存储结构深入分析
首先创建cluster :
CREATE CLUSTER personnel
( department_number NUMBER(2) ) ;
创建表emp:
CREATE TABLE emp
(empno NUMBER PRIMARY KEY,
ename VARCHAR2(10) NOT NULL
CHECK (ename = UPPER(ename)),
job VARCHAR2(9),
mgr NUMBER ,
hiredate DATE
CHECK (hiredate < TO_DATE ('08-14-1998', 'MM-DD-YYYY')),
sal NUMBER(10,2) CHECK (sal > 500),
comm NUMBER(9,0) DEFAULT NULL,
deptno NUMBER(2) NOT NULL )
CLUSTER personnel (deptno);
创建表dept:
CREATE TABLE dept
(deptno NUMBER(2),
dname VARCHAR2(9),
loc VARCHAR2(9))
CLUSTER personnel (deptno);
然后执行:
Insert into emp select * from scott.emp;
Insert into dept select * from scott.dept;
接下来dump相应而cluster,分析其存储结构:
Dump 文件如下:
Block header dump: 0x01000223
Object id on Block? Y
seg/obj: 0x11746 csc: 0x00.11d4bd itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x1000220 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0003.005.00000302 0x00c0081a.00ae.20 C--- 0 scn 0x0000.0011d49a
0x02 0x0003.007.00000302 0x00c0081a.00ae.25 --U- 1 fsc 0x0000.0011d4c0 表示该ITL 事务已经提交,但是提交的SCN是oracle 在数据有效性的基础上“猜”出来的,可能并不是真实的 commit scn ,这个SCN就是 scn/fsc
bdba: 0x01000223
data_block_dump,data header at 0x8407264
===============
tsiz: 0x1f98 total area size =8088 byte
hsiz: 0x24 header area size=36 byte
pbl: 0x08407264 pointer to the buffer hold the block
76543210
flag=--------
ntab=3 numbert of table (>1,所以此block为cluster的block) 分别为:cluster personnel emp dept
nrow=5 number of rows (有5行).
frre=-1
fsbo=0x24
fseo=0x1efd
avsp=0x1ed9
tosp=0x1ed9
0xe: pti[0] nrow=1 offs=0
0x12: pti[1] nrow=3 offs=1
0x16: pti[2] nrow=1 offs=4
0x1a: pri[0] offs=0x1f82
0x1c: pri[1] offs=0x1f5c
0x1e: pri[2] offs=0x1f39
0x20: pri[3] offs=0x1f15
0x22: pri[4] offs=0x1efd
block_row_dump:
tab 0, row 0, @0x1f82
tl: 22 fb: K-H-FL-- lb: 0x0 cc: 1 -----------fb:K-H-FL—表示这是一个cluster key,且此row包含row header,row first piece,row last piece,即没有发生分片.
curc: 4 comc: 4 pk: 0x01000223.0 nk: 0x01000223.0 ---------curc,comc这个怎么解释?
col 0: [ 2] c1 0b -----------------表示的deptno 为10
tab 1, row 0, @0x1f5c
tl: 38 fb: -CH-FL-- lb: 0x0 cc: 6 cki: 0 ---------- fb中的c表示cluster member table
col 0: [ 3] c2 4e 53 ---------- col 0:7782
col 1: [ 5] 43 4c 41 52 4b -------------col 1:CLARK
col 2: [ 7] 4d 41 4e 41 47 45 52 col 2: MANAGER
col 3: [ 3] c2 4f 28 col 3: 7839
col 4: [ 7] 77 b5 06 09 01 01 01 col 4:表示date类型,可以经过如下转换
77(hex)=119(decimal) centry=119-100=19
B5(hex)=181(decimal) year=181-100=81
06(hex)=06(decimal) month=06
09(hex)=09(decimal) day=09
01(hex)=01(decimal) hour=1-1=0
01(hex)=01(decimal) minute=1-1=0
01(hex)=01(decimal) seconds=1-1=0
col 5: [ 3] c2 19 33 col 5表示值为: 2450 col 6由于为null,所以没有存储,由此可见对于every row最后为null的列可以省略,节省了存储空间。
tab 1, row 1, @0x1f39
tl: 35 fb: -CH-FL-- lb: 0x0 cc: 6 cki: 0 -----------fb:K-H-FL—表示这是一个cluster key,且此row包含row header,row first piece,row last piece,即没有发生分片.
col 0: [ 3] c2 4f 28 col 0: 7839
col 1: [ 4] 4b 49 4e 47 col 1: KING
col 2: [ 9] 50 52 45 53 49 44 45 4e 54 col 2: PRESIDENT
col 3: *NULL* col3 :NULL NULL并没有实际的存储,只是在此显示而已,因为tl:为35,而row header占用了10byte,而数据占用了25byte,所以NULL并没有占用空间。
col 4: [ 7] 77 b5 0b 11 01 01 01 col 4:表示date类型,可以经过如下转换
77(hex)=119(decimal) centry=119-100=19
B5(hex)=181(decimal) year=181-100=81
0b(hex)=11(decimal) month=11
11(hex)=17(decimal) day=17
01(hex)=01(decimal) hour=1-1=0
01(hex)=01(decimal) minute=1-1=0
01(hex)=01(decimal) seconds=1-1=0
col 5: [ 2] c2 33 col5为: 5000 col 6由于为null,所以没有存储,由此可见对于every row最后为null的列可以省略,节省了存储空间。
tab 1, row 2, @0x1f15
tl: 36 fb: -CH-FL-- lb: 0x0 cc: 6 cki: 0 -----------fb:K-H-FL—表示这是一个cluster key,且此row包含row header,row first piece,row last piece,即没有发生分片.
col 0: [ 3] c2 50 23 ------------------col 0: 7934
col 1: [ 6] 4d 49 4c 4c 45 52 -------------------col 1: MILLER
col 2: [ 5] 43 4c 45 52 4b ------------------col 2: CLERK
col 3: [ 3] c2 4e 53 -----------------------col 3: 7782
col 4: [ 7] 77 b6 01 17 01 01 01 col 4:表示date类型,可以经过如下转换
77(hex)=119(decimal) centry=119-100=19
B6(hex)=182(decimal) year=182-100=82
01(hex)=01(decimal) month=01
17(hex)=25(decimal) day=25
01(hex)=01(decimal) hour=1-1=0
01(hex)=01(decimal) minute=1-1=0
01(hex)=01(decimal) seconds=1-1=0
col 5: [ 2] c2 0e col 5: 1300
tab 2, row 0, @0x1efd tab2 的行如下:
tl: 24 fb: -CH-FL-- lb: 0x2 cc: 2 cki: 0 -----------fb:K-H-FL—表示这是一个cluster key,且此row包含row header,row first piece,row last piece,即没有发生分片.
col 0: [10] 41 43 43 4f 55 4e 54 49 4e 47 ---------------- col 0: ACCOUNTING
col 1: [ 8] 4e 45 57 20 59 4f 52 4b -------------col 1: NEW YORK
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 547 maxblk 547
由上面dump内容分析可知具有相同的deptno的dept和emp表的行存储在同一个块中,如下查询清晰的验证了上面的分析(deptno为cluster key,提出来存储在第一行):
SQL> select * from emp where deptno=10;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7782 CLARK MANAGER 7839 09-6月 -81 2450 10
7839 KING PRESIDENT 17-11月-81 5000 10
7934 MILLER CLERK 7782 23-1月 -82 1300 10
SQL> select * from dept where deptno=10;
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
事实正如分析的那样。这样的存储方式使连接查询只需要scan少量的block就能得到想要的结果,降低了I/O,同时由于cluster key只存储一次,节省了存储了空间。然而,这些却降低了如dml或非链接查询的效率,因为每次CPU都要做额外的处理才能将数据按特定的方式进行插入,每次的非连接查询都要进行数据组装,因此合适选择使用cluster table因英勇的需求而定,如果因为大量的连接查询降低了效率,而使用cluster table带来性能提升的同时对系统的影响较小或没有影响,此时使用cluster table或许是一个不错的选择。