创建表时考虑列的顺序

本文介绍了Oracle建表时列顺序对性能的影响。Oracle行数据存储结构包括行头和列数据,查询时会检查列长度位。通过测试发现,查询首列比末列快约10%。建表时应将常用列放前面,主键列放中间,含较多NULL值的列放最后。

创建表时考虑列的顺序
创建一个表时表中列的顺序在某些程度上对性能会有一定的影响.(表中的列有数据)
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值的列可以放在最后面.可以终合考虑上面两点,根据系统的应用做相应操作.

<think>好的,我现在需要帮用户解答如何在Kingbase数据库中调整顺序。首先,我得回忆一下KingbaseES的文档和SQL语法。调整顺序数据库管理中属于结构修改的范畴,通常涉及ALTER TABLE语句。不过,标准的SQL并没有直接调整顺序的命令,因为顺序在物理存储中可能并不重要,但在逻辑上可能影响查询结果的显示。 用户提到的其他引用中,比如引用[1]和[2]是关于参数设置的,可能和性能优化有关,但调整顺序可能不直接相关。不过,引用[3]提到了多连接和优化器,引用[4]是关于WAL日志的结构,这些可能和结构调整后的性能或存储有关,但暂先不考虑这些。 首先,我需要确认KingbaseES是否支持类似Oracle的ALTER TABLE MODIFY COLUMN ... ORDER这样的语法。根据我了解,大部分数据库系统如PostgreSQL(KingbaseES基于PostgreSQL)并不直接支持调整顺序,需要通过间接方法实现。比如,创建一个新,按新顺序插入数据,然后重命名。或者使用ALTER TABLE语句添加新、调整的位置,但具体是否支持需要查证。 接下来,我需要检查KingbaseES的官方文档,特别是ALTER TABLE的语法部分。假设KingbaseES支持类似于PostgreSQL的ALTER TABLE ... ALTER COLUMN ... SET POSITION,但根据我的记忆,PostgreSQL本身并不支持这个功能。可能需要使用其他方法。 另外,用户可能希望在不丢失数据的情况下调整顺序。这候,可以通过以下步骤:1. 创建,按所需顺序定义;2. 将旧的数据插入到新;3. 删除旧;4. 重命名新为旧名。这种方法虽然可行,但需要注意约束、索引、权限等问题,可能比较繁琐。 或者,如果KingbaseES有扩展功能,比如像某些数据库系统提供的ALTER COLUMN POSITION,那就可以直接使用。需要确认这一点。例如,MySQL的ALTER TABLE允许使用AFTER关键字来调整的位置,但PostgreSQL不提供这个功能。而KingbaseES作为国产数据库,是否在语法上做了扩展? 另外,用户可能需要考虑事务处理,确保在调整过程中数据的一致性。使用BEGIN TRANSACTION,执行操作,然后COMMIT,避免中途出错导致数据不一致。 此外,对于大来说,直接重建可能会导致性能问题,比如锁间过长。这候可能需要分阶段操作,或者使用在线DDL工具,如果KingbaseES支持的话。 总结可能的步骤:1. 使用ALTER TABLE ADD COLUMN添加新;2. 将数据从旧复制到新;3. 删除旧;4. 重命名新为旧名。但这种方法只能调整的位置到末尾,不能插入到中间位置。因此,如果用户需要调整到中间位置,可能需要创建。 或者,是否有其他方法,比如使用视图来改变顺序,但这只是逻辑上的调整,并不实际改变的存储结构。 需要明确告诉用户,KingbaseES中调整顺序的标准方法,以及可能的限制。比如,直接修改顺序可能不被支持,必须通过重建的方式。同,需要注意备份数据,避免操作失误导致数据丢失。 最后,结合用户提供的引用,可能需要提到在调整结构后,相关的性能参数设置(如引用[2]中的work_mem)可能需要重新评估,或者调整WAL日志(引用[4])相关的配置,以优化DDL操作的性能。</think>在KingbaseES数据库中调整顺序需要通过重建结构实现,主要分为以下步骤: ### 一、标准操作方法 1. **创建** 使用新顺序创建: ```sql CREATE TABLE new_table ( col3 INT, col1 VARCHAR(20), col2 DATE ); ``` 2. **迁移数据** ```sql INSERT INTO new_table(col3, col1, col2) SELECT col3, col1, col2 FROM original_table; ``` 3. **替换原** ```sql DROP TABLE original_table; ALTER TABLE new_table RENAME TO original_table; ``` ### 二、扩展方法(使用系统函数) 通过`sys_dump`导出结构后修改顺序: ```bash sys_dump -t original_table --schema-only > table.sql # 手动修改顺序后执行 ksql -d dbname -f table.sql ``` ### 三、注意事项 1. **权限要求**:需要所有者权限或ALTER权限[^1] 2. **事务控制**:建议在事务块中操作 ```sql BEGIN; -- 执行重建操作 COMMIT; ``` 3. **索引重建**:所有依赖的索引需要重新创建 4. **外键约束**:需要先删除后重建
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值