1、数据库重构分成6类:
2、数据库味道
与“代码味道”概念相似,代码味道是代码中出现常见问题,表明需要进行重构。
数据库味道表明数据库需要重构。这些味道包括:
(1)多用途的列
如一个列被用于多种用途,就可能存在额外的代码来确保源数据以“正确的方式”使用,这些代码常常会检查一个列或更多其它列的值。
比如:
某列用于存储某人的生日,如果此人是顾客的话。假如此人是公司雇员,此列则用于存储入厂日期。
(2)多用途的表
如一个表被用于存放几种类型的实体,就可能存在设计缺陷。
例如:
某个表Customer同时存放了人和公司的信息。
(3)重复的数据
重复的数据对操作型数据库来说是一个严重的问题,因为如数据存放在几个地方,不一致的机会就增加了。
(4)列太多的表
当一个表包含太多的列,则说明这个表缺乏内聚。
比如:
Customer表包含了一些列,存放了3种不同的地址(发货地址、账单地址、公司地址)或几个电话号码(家庭电话、工作电话、手机号等),你可能需要将这种结构进行标准化处理,加入Address和PhoneNumber表。
(5)“智能”列
“智能”列是这样一种列,其中数据的不同位置代表不同的概念。
例如:
客户ID的前4位数字代表客户的开户行,则客户ID就是一个“智能”列。因为你会解析它以取得更细粒度的信息,如开户行ID。
3、数据库重构
数据库重构是一种数据库实现技术,与代码重构相似,对数据库Schema进行重构,使得在上面增加东西变得容易。
上图提供了一些关键开发活动的高层视图,这些活动发生在涉及对象和关系数据库技术的现代项目中。需要在这些活动之间来回迭代。
数据库重构是演进式数据库开发的一个重要组成部分。还需要采用演进/敏捷的方式进行数据建模。
耦合越厉害,就越难重构。代码重构、数据库重构均是如此。
最简单的场景:单应用数据库。因为数据库Schema只与它本身和一个应用相耦合。
而在多应用的数据库架构中,你的数据库Schema可能与应用源码、持久框架、ORM工具、其它数据库(提供复制、数据抽取/加载等)、数据文件Schema、测试代码,甚至数据库自身等耦合在一起。
减少涉及数据库的耦合的一种有效方式是封装对数据库的访问。让外部程序通过持久层来访问数据库,可以实现对数据库访问的封装。
持久层有多种实现方式:
(1)通过数据访问对象DAO,它实现了所需的SQL代码;
(2)通过框架;
(3)通过存储过程;
(4)通过Web服务。
永远也不可能把耦合降到0,但肯定可以把它降到能管理的程度。
4、数据库重构实例
“余额Balance”列实际上描述的是“账户Account”实体,而不是“顾客Customer”实体。
因此如图所示,需要把“余额Balance”列从“顾客Customer”表移出,加入到“账户Account”表中。
重构的迭代活动如下:
(1)验证数据库重构是否合适;
这个重构有意义吗?变更真的需要现在进行吗?值得这样去做吗?
(2)选择最合适的数据库重构技术;
真正需要重构的是“使用正式数据源”
(3)让原来的数据库Schema过时;
需要一个转换期,即“过时期”
(4)前测试、中测试和后测试;
要能够轻易验证数据库在变更之后仍能与应用一起工作,就有信心对数据库Schema进行变更,做到这一点的唯一途径就是采用测试驱动开发TDD的方式。
TDD方式中,编写一个测试,编写足够代码,通常是使用数据定义语言DDL,来完成该测试。继续以这种方式工作,直到数据库重构完全实现。
(4.1)测试数据库Schema;
数据库重构会影响数据库Schema,故需编写面向数据库的测试。可以从许多方面来检查数据库Schema:
1.存储过程和触发器
2.参照完整性RI
3.视图定义
4.缺省值
5.数据不变式
数据库测试工具:管理测试数据的工具DBUnit;测试存储过程的工具SQLUnit;还有针对数据测试的商业工具。
对每次重构采用一些小脚本,原因是:简单性、正确性、版本控制。
实现重构的一个重要方面是,确保数据库Schema变更的部署遵守了公司的数据库开发指南。
1.迁移源数据;
当发现需要编写支持文档来描述一个表、一个列或一个存储过程时,说明需要对这部分Schema进行重构,使其更易于理解。
也许一次简单的改名就可以避免几段说明文档。设计越清晰,就越少需要文档。
2.修改外部访问程序;
数据库Schema变更时,常常需要重构原有的外部程序。
3.运行回归测试;
实现重构的一部分工作是对它进行测试,确保它能工作。
4.对工作进行版本控制;
把重构置于配置管理CM的控制之下。
5.宣布此次重构。
需要向感兴趣的各方沟通已经完成的数据库重构。
宣布工作的一个重要方面是更新相关的文档。还需要更新数据库的物理数据模型PDM。
注意:不用发布不成熟的数据模型。
数据库重构过程:
小结:数据库重构的工作室在开发沙盒中完成的,最好是由一个开发者和一个DBA结对完成。
(4.2)测试应用程序使用数据库Schema的方式;
(4.3)检验数据迁移的有效性;
许多数据库重构技术要求迁移源数据,比如将数据值Customer.Balance复制到Account.Balance,需要检验每位顾客的正确余额确实进行了拷贝。
(4.4)测试外部程序代码。
6.修改数据库Schema;
以上面的例子,需要加入Account.Balance列和两个触发器:SynchronizeAccountBalance和SynchronizeCustomerBalance。
完成此事的DDL代码:
ALTER TABLE Account ADD Balance Numeric; COMMENT ON Account.Balance 'Move of Customer.Balance column, finaldate=2006-06-14'; CREATE OR REPLACE TRIGGER SynchronizeCustomerBalance BEFORE INSERT OR UPDATE ON Account REFERENCE OLD AS OLD NEW AS NEW FOR EACH ROW DECLARE BEGIN IF :NEW.Balance IS NOT NULL THEN UpdateCustomerBalance; END IF END; / COMMENT ON SynchronizeCustomerBalance 'Move of Customer.Balance column to Account, dropdate = 2006-06-14'; CREATE OR REPLACE TRIGGER SynchronizeAccountBalance BEFORE INSERT OR UPDATE OR DELETE ON Customer REFERENCE OLD AS OLD NEW AS NEW FOR EACH ROW DECLARE BEGIN IF DELETING THEN DeleteCustomerIfAccountNotFound; END IF IF (UPDATING OR INSERTING) THEN IF :NEW.Balance IS NOT NULL THEN UpdateAccountBalanceForCustomer; END IF; END IF; END; / COMMENT ON SynchronizeAccountBalance 'Move of Customer.Balance column to Account, dropdate=2006-06-14' |
|