前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Oracle中怎么导出索引数据块?

Oracle中怎么导出索引数据块?

作者头像
bisal
发布2022-05-10 14:20:28
6190
发布2022-05-10 14:20:28
举报

Oracle唯一索引和NULL空值之间的关系》文章写到了dump索引数据块,当我们需要看一些数据表、索引在块上的存储形式时,dump数据块是一种很直接的操作。

1. 创建测试表,含1000条数据,创建唯一索引,

代码语言:javascript
复制
SQL> create table tt1 as select owner, object_id, object_name from dba_objects where rownum < 1001;
Table created.


SQL> create unique index idx_tt1_01 on tt1(owner, object_id, object_name);
Index created.


SQL> select count(*) from tt1;
  COUNT(*)
----------
      1000

可知他现在有5个叶子节点块,索引层高为2,

代码语言:javascript
复制
SQL> select table_name,index_name,blevel,leaf_blocks,num_rows,last_analyzed,degree,status from user_indexes where table_name='TT1';
TABLE_NAME                INDEX_NAME                    BLEVEL LEAF_BLOCKS   NUM_ROWS LAST_ANALYZED      DEGREE                                   STATUS
------------------------- ------------------------- ---------- ----------- ---------- ------------------ ---------------------------------------- --------
TT1                       IDX_TT1_01                         1           5       1000 26-APR-22          1                                        VALID

2. 查询索引的object_id,

代码语言:javascript
复制
SQL> select object_id from user_objects where object_name='IDX_TT1_01';
 OBJECT_ID
----------
     73011

3. 查询索引的treedump,此处的参数,就是索引的object_id,

代码语言:javascript
复制
SQL> alter session set events 'immediate trace name treedump level 73011';
Session altered.

4. 到Oracle的trace路径下,可以直接cd,或者通过oradebug setmypid -> oradebug tracefile_name得到trace文件名,文件片段如下,可以看到有5个leaf,这和上面查询到的索引包含5个节点叶子块是一致的,

代码语言:javascript
复制
----- begin tree dump
*** 2022-04-25T19:08:55.943552+08:00 (BISALPDB1(3))
branch: 0x3002bbb 50342843 (0: nrow: 5, level: 1)
   leaf: 0x3002bbc 50342844 (-1: row:270.270 avs:837)
   leaf: 0x3002bbd 50342845 (0: row:225.225 avs:816)
   leaf: 0x3002bbe 50342846 (1: row:224.224 avs:840)
   leaf: 0x3002bbf 50342847 (2: row:234.234 avs:826)
   leaf: 0x3002bc0 50342850 (3: row:50.50 avs:6158)
----- end tree dump

5. 我们可以dump其中一个索引叶子节点的数据块,例如第五个leaf,根据值50342850,通过dbms_utility包的data_block_address_file和data_block_address_block就可以得到这个索引叶子节点对应的数据文件号、数据块号,此处是12号文件的第11200个数据块,

代码语言:javascript
复制
SQL> select dbms_utility.data_block_address_file(50342850) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(50342850)
----------------------------------------------
                                            12


SQL> select dbms_utility.data_block_address_block(50342850) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(50342850)
-----------------------------------------------
                                          11200

6. dump索引数据块,

代码语言:javascript
复制
SQL> alter system dump datafile 12 block 11200;
System altered.

从trace路径,就可以找到dump出来的文件,从以下位置开始,就是索引数据块的信息了,可以看到typ:2-INDEX表示他是个索引的数据块,

代码语言:javascript
复制
Block header dump:  0x03003b70
 Object id on Block? Y
 seg/obj: 0x11d33  csc:  0x0000000000f8b3d6  itc: 2  flg: E  typ: 2 - INDEX
     brn: 1  bdba: 0x3003b68 ver: 0x01 opc: 0
     inc: 0  exflg: 0


 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0x0008.00d.000007f7  0x024000f6.02bf.17  --U-    1  fsc 0x0000.00f8b3f1
Leaf block dump
===============
header address 1981317220=0x76188064
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 0
kdxconro 127
kdxcofbo 290=0x122
kdxcofeo 3435=0xd6b
kdxcoavs 3145
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 50346863=0x3003b6f
kdxledsz 6
kdxlebksz 8032
row#0[7990] flag: -------, lock: 0, len=42, data:(6):  03 00 2b d6 00 60
col 0; len 3; (3):  53 59 53
col 1; len 3; (3):  c2 09 4d
col 2; len 25; (25):
 53 59 53 5f 4c 4f 42 30 30 30 30 30 30 30 38 37 35 43 30 30 30 34 38 24 24
row#1[7949] flag: -------, lock: 0, len=41, data:(6):  03 00 2b d6 00 5f
col 0; len 3; (3):  53 59 53
col 1; len 3; (3):  c2 09 4e
col 2; len 24; (24):
 53 59 53 5f 49 4c 30 30 30 30 30 30 30 38 37 35 43 30 30 30 34 38 24 24
row#2[7907] flag: -------, lock: 0, len=42, data:(6):  03 00 2b d6 00 5e
col 0; len 3; (3):  53 59 53
col 1; len 3; (3):  c2 09 4f
col 2; len 25; (25):
 53 59 53 5f 4c 4f 42 30 30 30 30 30 30 30 38 37 35 43 30 30 30 34 39 24 24


...


row#125[3449] flag: -------, lock: 0, len=32, data:(6):  03 00 2b d6 00 da
col 0; len 3; (3):  53 59 53
col 1; len 3; (3):  c2 0b 02
col 2; len 15; (15):  41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f
row#126[3435] flag: -------, lock: 2, len=14, data:(6):  03 00 2b d7 00 00
col 0; len 1; (1):  61
col 1; len 2; (2):  c1 02
col 2; NULL
----- end of leaf block Logical dump -----
----- end of leaf block dump -----

以第126行为例,

第1行的data(6)是rowid,

第2-4行是第1-3列索引值,

代码语言:javascript
复制
row#125[3449] flag: -------, lock: 0, len=32, data:(6):  03 00 2b d6 00 da
col 0; len 3; (3):  53 59 53
col 1; len 3; (3):  c2 0b 02
col 2; len 15; (15):  41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f

1. rowid

"data:(6): 03 00 2b d6 00 da"是16进制的rowid,先转成二进制,

代码语言:javascript
复制
00000011 00000000 00101011 11010110 00000000 11011010

按照rowid组成规则,

(1) 对应文件编号,表明该行所在文件的编号,表空间的每一个文件标号都是唯一的,文件编号所占用的位置是10位,如下所示,

代码语言:javascript
复制
00000011 00,10进制的文件号:12

(2) 块编号,表明改行所在文件的块的位置块编号需要22位,如下所示,

代码语言:javascript
复制
000000 00101011 11010110,10进制的块号:11222

(3) 行编号,表明该行在行目录中的具体位置行编号需要16位,如下所示,

代码语言:javascript
复制
00000000 11011010,10进制的行号:218

即第126行的数据是在第10个数据文件中第11222个数据块的第218行。

2. 索引实际值

代码语言:javascript
复制
col 0; len 3; (3):  53 59 53
col 1; len 3; (3):  c2 0b 02
col 2; len 15; (15):  41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f

dump文件中的索引值,可以转成实际的索引列的值,此时可以借助travel大神的函数f_get_from_dump,原始下载地址,应该被墙了,常规操作不让访问了,

http://www.traveldba.com/wp-content/uploads/scripts/f_get_from_dump.sql

除了翻墙,可以从我的github下载,

https://github.com/bisal-liu/oracle/blob/master/f_get_from_dump

他支持数值类型、字符串类型、ROWID类型等的转换,以第126行为例,

(1) 第一列是VARCHAR2类型的,

代码语言:javascript
复制
col 0; len 3; (3):  53 59 53

调用函数f_get_from_dump,得到值SYS,

代码语言:javascript
复制
SQL> select f_get_from_dump('53,59,53','VARCHAR2') from dual;
F_GET_FROM_DUMP('53,59,53','VARCHAR2')
--------------------------------------------------------------------------------
SYS

(2) 第二列是NUMBER类型的,

代码语言:javascript
复制
col 1; len 3; (3):  c2 0b 02

调用函数f_get_from_dump,得到值1001,,

代码语言:javascript
复制
SQL> select f_get_from_dump('c2,0b,02','NUMBER') from dual;
F_GET_FROM_DUMP('C2,0B,02','NUMBER')
--------------------------------------------------------------------------------
1001

(3) 第三列是VARCHAR2类型的,

代码语言:javascript
复制
col 2; len 15; (15):  41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f

调用函数f_get_from_dump,得到值APPLY$_CDR_INFO,

代码语言:javascript
复制
SQL> select f_get_from_dump('41,50,50,4c,59,24,5f,43,44,52,5f,49,4e,46,4f','VARCHAR2') from dual;
F_GET_FROM_DUMP('41,50,50,4C,59,24,5F,43,44,52,5F,49,4E,46,4F','VARCHAR2')
--------------------------------------------------------------------------------
APPLY$_CDR_INFO

从这些数据块的文件中,我们就可以了解表的数据、索引的数据是怎么物理存储的,对于理解一些原理层的知识,非常有用,当然要做到融会贯通,从现象到本质,还得加以时日的训练,还在学习中。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-05-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档