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 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: 0x01000223Object id on Block? Yseg/obj: 0x11746 csc: 0x00.11d4bd itc: 2 flg: E typ: 1 - DATA brn: 0 bdba: 0x1000220 ver: 0x01 opc: 0 inc: 0 exflg: 0Itl Xid Uba Flag Lck Scn/Fsc0x01 0x0003.005.00000302 0x00c0081a.00ae.20 C--- 0 scn 0x0000.0011d49a0x02 0x0003.007.00000302 0x00c0081a.00ae.25 --U- 1 fsc 0x0000.0011d4c0 表示该ITL 事务已经提交,但是提交的SCN是oracle 在数据有效性的基础上“猜”出来的,可能并不是真实的 commit scn ,这个SCN就是 scn/fscbdba: 0x01000223data_block_dump,data header at 0x8407264===============tsiz: 0x1f98 total area size =8088 bytehsiz: 0x24 header area size=36 bytepbl: 0x08407264 pointer to the buffer hold the block 76543210flag=--------ntab=3 numbert of table (>1,所以此block为cluster的block) 分别为:cluster personnel emp deptnrow=5 number of rows (有5行).frre=-1fsbo=0x24fseo=0x1efdavsp=0x1ed9tosp=0x1ed90xe: pti[0] nrow=1 offs=00x12: pti[1] nrow=3 offs=10x16: pti[2] nrow=1 offs=40x1a: pri[0] offs=0x1f820x1c: pri[1] offs=0x1f5c0x1e: pri[2] offs=0x1f390x20: pri[3] offs=0x1f150x22: pri[4] offs=0x1efdblock_row_dump:tab 0, row 0, @0x1f82tl: 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, @0x1f5ctl: 38 fb: -CH-FL-- lb: 0x0 cc: 6 cki: 0 ---------- fb中的c表示cluster member tablecol 0: [ 3] c2 4e 53 ---------- col 0:7782col 1: [ 5] 43 4c 41 52 4b -------------col 1:CLARKcol 2: [ 7] 4d 41 4e 41 47 45 52 col 2: MANAGERcol 3: [ 3] c2 4f 28 col 3: 7839col 4: [ 7] 77 b5 06 09 01 01 01 col 4:表示date类型,可以经过如下转换77(hex)=119(decimal) centry=119-100=19B5(hex)=181(decimal) year=181-100=8106(hex)=06(decimal) month=0609(hex)=09(decimal) day=0901(hex)=01(decimal) hour=1-1=001(hex)=01(decimal) minute=1-1=001(hex)=01(decimal) seconds=1-1=0col 5: [ 3] c2 19 33 col 5表示值为: 2450 col 6由于为null,所以没有存储,由此可见对于every row最后为null的列可以省略,节省了存储空间。tab 1, row 1, @0x1f39tl: 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: 7839col 1: [ 4] 4b 49 4e 47 col 1: KINGcol 2: [ 9] 50 52 45 53 49 44 45 4e 54 col 2: PRESIDENTcol 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=19B5(hex)=181(decimal) year=181-100=810b(hex)=11(decimal) month=1111(hex)=17(decimal) day=1701(hex)=01(decimal) hour=1-1=001(hex)=01(decimal) minute=1-1=001(hex)=01(decimal) seconds=1-1=0col 5: [ 2] c2 33 col5为: 5000 col 6由于为null,所以没有存储,由此可见对于every row最后为null的列可以省略,节省了存储空间。tab 1, row 2, @0x1f15tl: 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: 7934col 1: [ 6] 4d 49 4c 4c 45 52 -------------------col 1: MILLERcol 2: [ 5] 43 4c 45 52 4b ------------------col 2: CLERKcol 3: [ 3] c2 4e 53 -----------------------col 3: 7782col 4: [ 7] 77 b6 01 17 01 01 01 col 4:表示date类型,可以经过如下转换77(hex)=119(decimal) centry=119-100=19B6(hex)=182(decimal) year=182-100=8201(hex)=01(decimal) month=0117(hex)=25(decimal) day=2501(hex)=01(decimal) hour=1-1=001(hex)=01(decimal) minute=1-1=001(hex)=01(decimal) seconds=1-1=0col 5: [ 2] c2 0e col 5: 1300tab 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: ACCOUNTINGcol 1: [ 8] 4e 45 57 20 59 4f 52 4b -------------col 1: NEW YORKend_of_block_dumpEnd 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 10SQL> 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或许是一个不错的选择。