如何找到某個鍵值在索引中存在於哪個BLOCK中

zhang41082發表於2019-01-19
比如我想知道我的EMAIL在測試系統中存在了什麼位置,那就需要DUMP BLOCK來檢視了,可是索引不像資料,資料的話我只要知道ROWID,然後根據ROWID得到資料存在於哪個資料檔案的哪個塊中,然後直接DUMP這個BLOCK就可以了。可是索引存了ROWID,但是你卻SELECT不出來,下面來演示下怎麼找到一個值在索引中存在於什麼地方[@more@]

首先得到索引的OBJECT_ID,然後DUMP出這個索引的根資訊:
SQL> select DATA_OBJECT_ID,OBJECT_ID from dba_objects where object_name='IDX_MEMBERIDENTITY_IDCONTENT';

DATA_OBJECT_ID OBJECT_ID
-------------- ----------
130792 130792
然後DUMP這個索引樹
SQL> alter session set events 'immediate trace name treedump level 130792';

Session altered

然後找到DUMP出來的TRACE檔案,內容大致如下:
----- begin tree dump
branch: 0x8465e8d 138829453 (0: nrow: 240, level: 2)
branch: 0x8466296 138830486 (-1: nrow: 353, level: 1)
leaf: 0x8465e8e 138829454 (-1: nrow: 224 rrow: 223)
leaf: 0x8465e8f 138829455 (0: nrow: 195 rrow: 195)
leaf: 0x8465e90 138829456 (1: nrow: 197 rrow: 197)
說明這個索引是兩層的,後面的NROW和RROW分別表示這個塊可以存放多少行資料以及目前存放了多少行資料,從上面可以看到索引的根節點的地址是138829453,那麼可以透過下面的方式得到這個根節點存在於哪個BLOCK中:
SQL> SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(138829453) "file",
2 DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(138829453) "block"
3 FROM DUAL;

file block
---------- ----------
33 417421
然後把33號檔案的417421號BLOCK DUMP出來,就可以看到根節點中的內容:
SQL> alter system dump datafile 33 block 417421;

System altered
然後把EMAIL:轉換成16進位制,去根TRACE檔案中的值進行對比,就可以發現EMAIL值是存在於哪個葉節點下面的,首先轉換EMAIL到16進位制:
SQL> select utl_raw.cast_to_raw() from dual;

UTL_RAW.CAST_TO_RAW('ZHANG4108
--------------------------------------------------------------------------------
7A68616E673431303832403136332E636F6D

因為索引中存的16進位制都是小寫的,而且每個字元中間是有空格的,所以格式化後的EMAIL的16進製為:
7a 68 61 6e 67 34 31 30 38 32 40 31 36 33 2e 63 6f 6d

根據這個字串到剛才DUMP出來的根節點去對比,可以找到下面一段:
row#227[6288] dba: 139652795=0x852eebb
col 0; len 4; (4): 79 7a 67 30
col 1; TERM
row#228[6493] dba: 138917985=0x847b861
col 0; len 9; (9): 7a 65 6e 67 79 61 6e 67 61
col 1; TERM
row#229[5114] dba: 140549035=0x8609bab
col 0; len 8; (8): 7a 68 61 6e 67 67 68 32

可以看到EMAIL轉換後的16進位制是在上面這兩個值中間的,那說明EMAIL是存放在139652795葉節點下面的,那下面就來找到這個葉節點並把它DUMP出來:
SQL> SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(138917985) "file",
2 DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(138917985) "block"
3 FROM DUAL;

file block
---------- ----------
33 505953
SQL> alter system dump datafile 33 block 505953;

System altered
在葉節點DUMP出來的TRACE檔案中可以找到下面的地方:
row#291[6494] dba: 138917683=0x847b733
col 0; len 9; (9): 7a 68 61 6e 67 34 31 30 33
col 1; TERM
row#292[6509] dba: 138917684=0x847b734
col 0; len 16; (16): 7a 68 61 6e 67 34 34 31 36 35 35 36 32 34 36 40
這說明最後的EMAIL是在索引中的位置是存放在138917683對應的BLOCK中的,接下來把這個BLOCK DUMP出來:
SQL> SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(138917683) "file",
2 DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(138917683) "block"
3 FROM DUAL;

file block
---------- ----------
33 505651
SQL> alter system dump datafile 33 block 505651;

System altered
最後可以在DUMP出來的BLOCK中找到下面內容:
row#5[1104] flag: ------, lock: 0, len=32
col 0; len 18; (18): 7a 68 61 6e 67 34 31 30 38 32 40 31 36 33 2e 63 6f 6d
col 1; len 10; (10): 00 01 f6 3b 09 87 52 5b 00 28
這個地方就是EMAIL在這個索引中真正存在的內容,其中COL0表示的是EMAIL的16進位制,然後COL1表示的是這個EMAIL對應的ROWID,至於這個ROWID怎麼還原成真正的ROWID,那下次在來完成吧。

另外,這裡只是一個簡單的索引,那麼如果是分割槽索引、壓縮索引或者複合索引、函式索引等等,情況可能會略有差別

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25016/viewspace-1020075/,如需轉載,請註明出處,否則將追究法律責任。

相關文章