創建表時考慮列的順序

發表于:2007-06-08來源:作者:點擊數: 標簽:
創建表時考慮列的順序 創建一個表時表中列的順序在某些程度上對 性能 會有一定的影響.(表中的列有數據) Oracle對行數據的存儲結構ROW HEADER(行頭)和COLUMN DATA(列數據).ROW HEADER存儲的信息是一個FLAG BYTE,一個LOCK BYTE 和COLUMN COUNT.COLUMN DATA包含

創建表時考慮列的順序
創建一個表時表中列的順序在某些程度上對性能會有一定的影響.(表中的列有數據)
Oracle對行數據的存儲結構ROW HEADER(行頭)和COLUMN DATA(列數據).ROW HEADER存儲的信息是一個FLAG BYTE,一個LOCK BYTE 和COLUMN

COUNT.COLUMN DATA包含COLUMN LENGTH和COLUMN DATA

關于這些我們可以DUMP個表做一下測試
create test as select * from dba_objects;
select header_file,header_block from dba_segments where owner='TEST' and segment_name='TEST';

HEADER_FILE    HEADER_BLOCK
------------------------   ---------------------------
                   13                      1179
alter system dump datafile 13 block 1180

得出來的文件在UDUMP中.我們查看如下信息
block_row_dump:
tab 0, row 0, @0x1f20
tl: 96 fb: --H-FL-- lb: 0x0  cc: 13--------row header信息.
col  0: [ 3]  53 59 53-------------------COLUMN DATA
fb: --H-FL-- 是FLAG BYTE. 
fb Flag Byte:
K = Cluster Key (Flags may change meaning if this is set to show HASH cluster)
C = Cluster table member
H = Head piece of row
D = Deleted row
F = First data piece
L = Last data piece
P = First column continues from previous piece
N = Last column continues in next piece
lb: 0x0-----------LOCK BYTE,鎖信息
cc: 13------------COLUMN COUNT
col  0---------第一列
[ 3]-------------COLUMN LENGTH
  53 59 53---------實際數據

這里一些信息可以參考grassbell寫的文章<<偷窺Data block 的物理結構>>.對每一個列,在每一個列數據前都含有列長度.在做查詢時,查詢行中某個

列的值,Oracle首先做的是檢查這些相關列的長度位.這個操作比較快而且效率較高.但是如果反復頻繁的這樣子做還是會帶來性能方面的影響.
下面的例子中創建了一個有10列的表并插入數據.
先設置DB_BLOCK_SIZE=2K(用參數設置,在這里設置為這個只是為了測試方便)
SQL> create table small (
  2    n0 number,
  3    n1 number,
  4    n2 number,
  5    n3 number,
  6    n4 number,
  7    n5 number,
  8    n6 number,
  9    n7 number,
 10    n8 number,
 11    n9 number
 12  ) pctfree 0;

Table created.

SQL> begin
  2    for i in 1..78 loop
  3      insert into small values (0,0,0,0,0,0,0,0,0,0);
  4    end loop;
  5  end;
  6  /

PL/SQL procedure successfully completed.

SQL> set timing on
SQL> declare
  2    n number;
  3  begin
  4    for i in 1..1000000 loop
  5      select sum(n0) into n from small;
  6    end loop;
  7  end;
  8  /

PL/SQL procedure successfully completed.

Elapsed: 00:07:437.30
SQL> declare
  2    n number;
  3  begin
  4    for i in 1..1000000 loop
  5      select sum(n9) into n from small;
  6    end loop;
  7  end;
  8  /

PL/SQL procedure successfully completed.

Elapsed: 00:08:482.13

從上面的例子很明顯可以看到在一個表中做查詢時,查詢的數據和列的屬性都是一樣的,但是所查的列位于第一列時查詢速度比在第10快了差不多

10%.所以在建表的時候規則就是根據應用將表中經常訪問的列放面前面.建表時一般都有一個PRIMARY KEY的列,像這種屬性的列一般我們直接訪

問的并不多.所以我們一般不放在第一列.關于這個其實如果我們有注意到的話,Oracle本身字典內表也是這樣子的.
desc dba_objects看看.或者其他的表可以試試.

還有另外一個要考慮的列的位置的就是列中含有較多的NULL值時所要放的位置.
Oracle存儲NULL值時,一行中某個列存在NULL值,而這一列的后面的列中存在有數據(非NULL),則Oracle會分配1byte來存放NULL.如果這一列的后面

沒有列或者都是NULL值時.這一列和后面的NULL值Oracle都不做存儲.列信息也不存儲.這一點可以看以下例子.

SQL> create table null_order (
  2    column1 number,
  3    column2 number,
  4    column3 number
  5  );

Table created.

SQL> insert into null_order (column2) values (0);

1 row created.

SQL> select header_file, header_block from dba_segments
  2  where segment_name = 'TEST' and owner = 'TEST';

HEADER_FILE HEADER_BLOCK
----------- ------------
          3        50010

SQL> alter system dump datafile 3 block 50011;

System altered.

然后查看DUMP出來的文件的相關信息
block_row_dump:
tab 0, row 0, @0x7b2
tl: 6 fb: --H-FL-- lb: 0x1 cc: 2
col  0: *NULL*--------------第一列的NULL
col  1: [ 1]  80----------------第二列的值(后面沒有了第三列的值)
end_of_block_dump

結論:創建一個表時,可以將我們經常訪問到的列放在表的前面.一般很少直接SELECT出來的PRIMARY KEY列可以放到中間來.列中如果可能會含有

較多NULL值的列可以放在最后面.可以終合考慮上面兩點,根據系統的應用做相應操作.


原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97