Oracle数据库是目前为止最复杂的一个数据库之一。也正是这种复杂性,让Oracle数据库能够面对企业各种各样的需求。不过大部分时候,数据库管理员掌握一些技巧,可以让数据库维护工作变得简单。笔者这里就以Oracle数据库中表列的管理为例,谈谈这方面的问题。
一、 把列设置为UNUSED状态,代替删除。
当数据库部署完成之后,即使在数据库使用过程中,数据库管理员仍然可以对数据库的表进行维护,如删除列等等。删除列将删除表中每条记录的相应列的值,同时释放其所占用的存储空间。所以如果要删除一个大表中的列时,由于其必须对每条记录都进行相应的处理,为此这个删除列的操作会占用比较长的时间。如有个数据库管理员一次在设计一个人员管理系统时,一开始是把人员的住址跟人员信息表放置同一个表中。可是后来证明这个设计是错误的。一方面因为人员住址的字段比较长,而且有些由于住址难以确定,这个字段还是空的。另一方面,一个人员其可能住址变更了好几次,而出于管理的需要,又要保存起以前的住址信息。为此最后一个人员可能同时对应多个住址信息。所以后来数据库管理员调整了设计,另外建立了一张表,然后利用人员编号把它们关联起来。由于那时表中的纪录已经比较多了,如果要删除列的话,那么可能这个删除作业需要执行时间比较长。
为了避免在数据库使用高峰期间由于执行删除列的操作而占用过多的系统资源(而且时间比较长),为此笔者建议不要马上采用DROP关键字来删除列。而可以先用UNUSED关键字把某个列设置为不活跃状态。如可以利用命令ALTER TABLE ADRESS SET UNUSED,把某个列设置为不活跃。如此设置之后,从用户的角度来看,被设置为UNUSED状态的列于被直接删除的列之间是没有任何区别的。用户无法通过查询或者在数据字典中看到这些列。而且即使在表中,也可以插入相同列名的列。简单的说,对于用户来说,这个设置为UNUSED的列就好像删除了一样。但是从数据库角度来说,在是不一样的。其这个列只是别设置为UNUNSED列,但是在数据库中仍然是存在的。也就是说,这个列所占用的存储空间没有被释放。为此即使在数据库运行的高峰时期,为列加入这个标记也不会占用多少的时间和系统资源。
为此,笔者的意见是,当数据库比较繁忙时而且数据库表中的纪录又比较多,则可以不从物理上删除这个列,而先把这个列标记为UNUSED状态。这可以减少因为删除列而给数据库正常使用带来的负面影响。虽然这要牺牲一点硬盘空间,可是现在硬盘便宜。为了数据库的性能,牺牲这点硬盘空间是值得的。等到数据库比较空的时候,再把这些列删除即可。这对于用户来说,是不会受到任何影响的。这只是在技术处理上的问题。
为了便于管理这些UNUSED列,在Oracle数据库中还提供了一张视图(这张视图的名字为USER_UNUSED_COL_TABS),帮助数据库管理员来管理这些列。通过查询这张视图,数据库管理员可以了解数据库哪些表中存在UNUSED列。然后数据库管理员可以根据实际情况,一个月或者一年来清除一下。这不仅可以提高数据库的运行效率,而且也不会因为删除列的操作影响到用户的正常使用。
二、 给列表添加相关的注释。
俗话说,好记性不如烂笔头。在数据库设计的时候,给表或者列添加一些必要的注释,可以提高其可读性,也有利于后续的维护与升级。像笔者这种专业的数据库设计与开发人员,往往一个人需要负责很多项目,即同时要负责多个企业的数据库软件。当项目数量一多,一年后可能就不知道某个数据库的某张表到底用来做什么用途。即使采用了比较合适的表名字编码或者列名字编码规则,但是凭借这些简单的代码,仍然不能够直观的反应出这些代码的含义。为此,在必要的时候,我们往往需要给表或者列添加相关的注释,方便后续对其进行维护与升级。
为了实现这个目的,我们可以利用COMMENT关键字。如COMMENT ON TABLE 表名 IS ‘注释内容’即可。在使用这个命令的时候需要注意的是,注释中的内容必须利用单引号括起来,而不是使用双引号。因为如果注释中含有特殊字符的话,如单引号、通配符等等,最好能够采用其他的字符代替。如果非要用这些字符的话,那么就需要采用转义字符,让数据库系统认为这是普通的字符。通常情况下,注释的内容可以多大4000个字节,足够数据库管理员用来表述表的用途。另外在注释的内容中可以包含标点符号、空格字符、特殊字符(不建议使用)等等。而且还可以跨越多个物理行,以提高可读性等等。不过虽然其提供了长达4000个字节的说明,但是数据库管理员在写注释的时候,最好能够短话短说。不然的话,以后要花大量的时间来读这些备注的内容,可不是一件好差事。未必笔者认为,在写这个表注释的时候,最好能够点到为止,而不要想写项目说明书那样写的面面俱到。
除了给表添加注释外,在Oracle数据库中还可以给列添加注释。这个添加的方法跟上面的类似,只需要把关键字ON TABLE更改为ON COLUMN 即可。当有多个人共同开发一个数据库时,最好能够在表或者列中添加必要的注释。即使不在这里添加说明,那么在独立的设计文档中,也需要进行详细的说明。一般情况下,笔者认为需要说明如下内容。一是创建者(谁创建的或者谁更新的);二是创建的时间(什么时候创建或者什么时候更新的);三是需要注明创建或者更新的目的;四是要注明这个列的一些约束条件。另外需要注意的是,如果后来有人更新这个表或者列的时候,如调整某个字段的大小,最好不要把原先的注释覆盖掉。而是直接在原有的注释后面加入新的注释。这些措施有利于后续的维护以及数据库的升级。
三、 重新组织表。
有时候出于改善数据库表的性能等目的出发,需要对Oralce数据库的表进行重新组织。如在Oracle数据库中,如果对表进行频繁的DML操作,会使得这个表产生比较多的空间碎片与行迁移,从而给数据库的性能带来负面影响。这种情况在一些事务型的数据库中是比较常见的。此时就需要重新组织表,如可以将移动一个位置,从而减少碎片,提高数据库的性能。
大部分情况下,笔者都是利用ALTER TABLE MOVE语句来重新组织表。如可以利用这条语句,将某个表移动到同一个表空间的新数据段中。移动以后这对于用户来说是没有任何影响的。但是却可以重建表的存储结构,从而减少碎片,优化性能。当然,也可以利用这个语句把现有的表移动到其他的表空间中去。不过在使用这个语句的时候,数据库管理员还是需要注意几个限制。
一是在使用这条语句中要注意有足够的空闲空间;如果在同一个表空间进行移动的话,则需要主要表空间能够容纳这个数据。这注意是因为,这个操作就好像是两个操作结合而完成的一项操作。其首先将这个表复制到指定的位置,然后再删除原来的表。也就是说,直到表被完全移到新的数据段中之后,数据库才会删除原来的数据段。所以这个空闲空间一定要保证,否则的话,就可能导致这个作业无法顺利完成。
二是在利用这个语句重新组织表的过程中,原表的ROWID会发生改变。而这个值改变后最大的影响就会使得表中的索引失效。为此在使用这个语句重新组织表之后,就需要对此表重新建立索引。这也就是说,在短时间内用户使用这个表会受到一定的影响。为此在执行这个操作的时候,最好能够选择数据库比较空闲的时候。如果在执行这个语句时能够暂时中断用户的连接,那时最好的。
数据库管理员可以通过数据字典来查询存储空间的碎片状态。如果碎片确实比较多的话,在笔者推荐使用这个语句来重新组织表,以减少碎片空间。如果整个数据库存储空间中都分布着大量的碎片,而不是个别表的问题,那么就需要采用数据泵工具来重新组织全部的表,在最大程度上减少碎片。