[20141008]索引字串的長度問題.txt
[20141008]索引字串的長度問題.txt
--oracle 的B tree 索引,一般儲存方式是長度+鍵值+...+長度+rowid鍵值,如果索引唯一,rowid在前面(沒有長度指示器),這樣可以節省1個位元組.
--但是如果索引的字串長度長度比如超過255個字元,這樣索引的長度部分如何儲存呢?
--曾經寫過一篇"varchar2(4000)如何儲存",連結如下:
http://blog.itpub.net/267265/viewspace-747304/
如果一行能被儲存於一個資料塊(data block)中,那麼其行頭(row header)所需容量將不少於 3 位元組(byte)。在行頭資訊之後依次
儲存的是各列的列長(column length)及列值(column value)。列長儲存於列值之前,如列值不超過250 位元組,那麼 Oracle使用1位元組存
儲其列長;如列值超過 250 位元組,則使用 3 位元組儲存其列長。列資料(column data)所需的儲存空間取決於此列的資料型別(datatype)。
如果某列的資料型別為變長(variable length)的,那麼儲存此列值所需的空間可能會隨著資料更新而增長或縮小。
總結:
1.如果列值長度小於等於250位元組,Oracle使用1位元組儲存其列長.內容為欄位的長度.
2.如果列值長度超過250位元組,則使用3位元組儲存其列長。前面1個位元組使用0xfe(表示超過250),後面2個位元組表示列值長度.
--所以,我開始想這個應該跟字串在資料塊的儲存方式一致,實際情況呢?做一個測試看看:
1.建立測試環境:
SCOTT@test> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
create table t ( a varchar2(200),b varchar2(3000));
insert into t values (lpad('1',127,'1'),lpad('a',127,'a'));
insert into t values (lpad('2',127,'2'),lpad('b',128,'b'));
insert into t values (lpad('3',127,'3'),lpad('c',1000,'c'));
commit;
create index i_t_a_b on t(a,b);
exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'t', estimate_percent=>null, method_opt=>'FOR ALL COLUMNS SIZE 1');
2.轉儲索引資訊:
SCOTT@test> select segment_name,header_file,header_block from dba_segments where owner=user and segment_name='I_T_A_B';
SEGMENT_NAME HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
I_T_A_B 4 562
--4*127+128+1000=1636,可以估計應該都儲存在索引的root節點.為EADER_BLOCK+1.
alter system checkpoint ;
alter system dump datafile 4 block 563 ;
Leaf block dump
===============
header address 182927614564=0x2a9755e264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 0
kdxconro 3
kdxcofbo 42=0x2a
kdxcofeo 6361=0x18d9
kdxcoavs 6319
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[7767] flag: ------, lock: 0, len=265
col 0; len 127; (127):
31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31
...
31 31
col 1; len 127; (127):
61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
...
61 61
col 2; len 6; (6): 01 00 02 13 00 00
row#1[7500] flag: ------, lock: 0, len=267
col 0; len 127; (127):
32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
...
32 32
col 1; len 128; (128):
62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62
...
62 62 62
col 2; len 6; (6): 01 00 02 13 00 01
row#2[6361] flag: ------, lock: 0, len=1139
col 0; len 127; (127):
33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33
...
33 33
col 1; len 1000; (1000):
63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
....
63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
col 2; len 6; (6): 01 00 02 13 00 02
----- end of leaf block dump -----
End dump data blocks tsn: 4 file#: 4 minblk 563 maxblk 563
--可以發現第一條索引條目前面的flag,lock佔用2個位元組 1+127+1+127+1+6=263, 2+263=265,正好符合.
--但是第二條索引條目,僅僅b欄位增加1個位元組,應該總廠266才對,而實際上是267.why?
SCOTT@test> @10to16 1000
10 to 16 HEX REVERSE16
-------------- ------------------
00000000003e8 0xe8030000
--從轉儲內容看:
Dump of memory from 0x0000002A9755E200 to 0x0000002A97560200
2A9755E200 0000A206 01000233 B7C4186D 04010002 [....3...m.......]
2A9755E210 0000C7B6 00046F02 0004735E B7C4186B [.....o..^s..k...]
2A9755E220 00000002 00320002 01000230 00000000 [......2.0.......]
2A9755E230 00000000 00000000 00000000 00000000 [................]
2A9755E240 00000000 0000FFFF 00000000 00000000 [................]
2A9755E250 00000000 00028000 B7C4186B 00000000 [........k.......]
2A9755E260 00000000 03800000 00000000 002A0003 [..............*.]
2A9755E270 18AF18D9 00000000 00000000 00000000 [................]
2A9755E280 00000000 00001F60 1D4C1E57 AAAA18D9 [....`...W.L.....]
2A9755E290 AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA [................]
Repeat 118 times
2A9755EA00 AAAAAAAA AAAAAAAA 00000000 00000000 [................]
2A9755EA10 00000000 00000000 00000000 00000000 [................]
Repeat 273 times
2A9755FB30 00000000 00000000 00000000 7F000000 [................]
2A9755FB40 33333333 33333333 33333333 33333333 [3333333333333333]
Repeat 6 times
2A9755FBB0 33333333 33333333 33333333 83333333 [333333333333333.]
2A9755FBC0 636363E8 63636363 63636363 63636363 [.ccccccccccccccc] <==83e8 表示欄位b的長度1000,而1000的16進製表示是0x03e8.
2A9755FBD0 63636363 63636363 63636363 63636363 [cccccccccccccccc]
Repeat 60 times
2A9755FFA0 63636363 63636363 00010663 02001302 [ccccccccc.......]
2A9755FFB0 327F0000 32323232 32323232 32323232 [...2222222222222]
2A9755FFC0 32323232 32323232 32323232 32323232 [2222222222222222]
Repeat 6 times
2A97560030 80803232 62626262 62626262 62626262 [22..bbbbbbbbbbbb] <=== 8080 表示欄位b的長度128,可以猜測另外80表示長度大於等於128.
2A97560040 62626262 62626262 62626262 62626262 [bbbbbbbbbbbbbbbb]
Repeat 6 times
2A975600B0 62626262 02000106 00010013 31317F00 [bbbb..........11]
2A975600C0 31313131 31313131 31313131 31313131 [1111111111111111]
Repeat 6 times
2A97560130 31313131 31313131 31313131 61617F31 [1111111111111.aa] <=== 7F 表示欄位b的長度127
2A97560140 61616161 61616161 61616161 61616161 [aaaaaaaaaaaaaaaa]
Repeat 6 times
2A975601B0 61616161 61616161 61616161 00010661 [aaaaaaaaaaaaa...]
2A975601C0 00001302 00000000 00000000 00000000 [................]
2A975601D0 00000000 00000000 00000000 00000000 [................]
Repeat 1 times
2A975601F0 00000000 00000000 00000000 186D0601 [..............m.]
對比轉儲,可以猜測與總結如下:
1.當字串長度小於等於127時,使用1個位元組表示長度.
2.當字串大於等於128時,使用2個位元組來儲存長度,內容為字串長度+0x8000.
3.真搞不懂為什麼與資料塊的儲存方式不同,oracle要創造2種不同的方式儲存字串.
--補充透過bbed觀察看看.
BBED> set dba 4,563
DBA 0x01000233 (16777779 4,563)
BBED> p kd_off
sb2 kd_off[0] @132 8032
sb2 kd_off[1] @134 0
sb2 kd_off[2] @136 7767
--kd_off[1] 指向 0,難道中間靠前面的資訊來推斷嗎? 這個東西不是很理解,先放一下.
BBED> p *kd_off[2]
rowdata[1410]
-------------
ub1 rowdata[1410] @7867 0x00
BBED> x /rccx
rowdata[1410] @7867
-------------
flag@7867: 0x00 (NONE)
lock@7868: 0x00
data key:
col 0[127] @7870: 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
col 1[127] @7998: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
col 2[6] @8126: 0x01 0x00 0x02 0x13 0x00 0x00
BBED> dump /v offset 7997 count 32
File: /u01/app/oracle11g/oradata/test/users01.dbf (4)
Block: 563 Offsets: 7997 to 8028 Dba:0x01000233
---------------------------------------------------------------------------------------------------------------------------------------------------------------
7f616161 61616161 61616161 61616161 61616161 61616161 61616161 61616161 l .aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
<48 bytes per line>
-- 0x7f=127.
BBED> set offset 7600
OFFSET 7600
BBED> x /rccx
rowdata[1143] @7600
-------------
flag@7600: 0x00 (NONE)
lock@7601: 0x00
data key:
col 0[127] @7603: 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
col 1[128] @7732: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
col 2[6] @7861: 0x01 0x00 0x02 0x13 0x00 0x01
BBED> dump /v offset 7730 count 32
File: /u01/app/oracle11g/oradata/test/users01.dbf (4)
Block: 563 Offsets: 7730 to 7761 Dba:0x01000233
---------------------------------------------------------------------------------------------------------------------------------------------------------------
80806262 62626262 62626262 62626262 62626262 62626262 62626262 62626262 l ..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
<48 bytes per line>
--8080表示長度128.
BBED> set offset 6461
OFFSET 6461
BBED> x /rccx
rowdata[4] @6461
----------
flag@6461: 0x00 (NONE)
lock@6462: 0x00
data key:
col 0[127] @6464: 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
col 1[1000] @6593: ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
...
cccc
col 2[6] @7594: 0x01 0x00 0x02 0x13 0x00 0x02
BBED> dump /v offset 6591 count 32
File: /u01/app/oracle11g/oradata/test/users01.dbf (4)
Block: 563 Offsets: 6591 to 6622 Dba:0x01000233
---------------------------------------------------------------------------------------------------------------------------------------------------------------
83e86363 63636363 63636363 63636363 63636363 63636363 63636363 63636363 l ..cccccccccccccccccccccccccccccc
<48 bytes per line>
--83e8 表示長度1000.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-1291526/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [20141008]使用bbed檢視索引結構.txt索引
- 取字串長度字串
- input最大長度限制問題
- 取字串左邊指定長度的子字串字串
- 取字串右邊指定長度的子字串字串
- ZT:字元長度與共享問題字元
- 求字串中對稱的子字串的最大長度字串
- shell獲取字串長度字串
- [20180509]函式索引問題.txt函式索引
- 擷取指定長度字串長度程式碼例項字串
- [20181229]關於字串的分配問題.txt字串
- 資料庫系列:字首索引和索引長度的取捨資料庫索引
- String字串的最大長度是多少?字串
- 求給定字串的平均字元長度字串字元
- QT生成固定長度的隨機字串QT隨機字串
- [20121028]IOT的第2索引-NULL的問題.txt索引Null
- [20180212]函式索引問題.txt函式索引
- 按位長度進行字串的分割輸出,長度不足補0字串
- c# word操作篇,解決字串長度超過255就不能替換的問題C#字串
- [20121016]字串長度與繫結變數的子游標.txt字串變數
- golang 計算最長不重複字串長度Golang字串
- MySQL中需要注意的欄位長度問題MySql
- [20150803]使用函式索引注意的問題.txt函式索引
- jQuery Validate限定輸入字串的長度jQuery字串
- 字串最後一個單詞的長度字串
- 生成固定長度不重複的隨機字串隨機字串
- 原生javascript實現的檢測字串長度JavaScript字串
- 獲取字串長度的幾個常用方法字串
- Longest Common Prefix字串最長公共字首問題字串
- 表單限制字串輸入長度字串
- JavaScript計算字串位元組長度JavaScript字串
- 淺談MySql整型索引和字串索引失效或隱式轉換問題汊叄MySql索引字串
- 字串問題字串
- 關於FileDownloader檔案長度校驗的問題
- Logmnr獲取SQL長度超過4000的問題SQL
- 函式索引的問題函式索引
- (字串雜湊表)找到字串中不重複出現字元的最長子串長度字串字元
- [20190918]關於函式索引問題.txt函式索引