Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2088586
  • 博文数量: 1647
  • 博客积分: 80000
  • 博客等级: 元帅
  • 技术积分: 9980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 15:15
文章分类

全部博文(1647)

文章存档

2011年(1)

2008年(1646)

我的朋友

分类:

2008-10-28 17:45:22


  创建表时考虑列的顺序
  
  创建一个表时表中列的顺序在某些程度上对性能会有一定的影响.(表中的列有数据)
  
  对行数据的结构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 的物理结构>>.对每一个列,在每一个列数据前都含有列长度.在做查询时,查询行中某个
  
  列的值,首先做的是检查这些相关列的长度位.这个操作比较快而且效率较高.但是如果反复频繁的这样子做还是会带来性能方面的影响.
  下面的例子中创建了一个有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值的列可以放在最后面.可以终合考虑上面两点,根据系统的应用做相应操作.
【责编:admin】

--------------------next---------------------

阅读(495) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~