王洋
摘要:该文主要是针对数据库设计中遇到实体的动态属性的问题,分别结合关系型和非关系型两大类数据库技术,介绍解决实体属性可变性问题的解决方法:关系弄的解决方案是改行为列和使用两个关系实体,非关系型的解决方案是采用HBase模型和MongoDB模型。这些方案为开发用户的数据需求提供多种可选方案,极大地为用户提供了方便。
關键词: 实体动态属性;数据库设计;关系数据库;非关系数据库
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)05-0009-02
1 问题的提出
随着大数据时代的来临,结构化数据、半结构化数据与非结构化数据已广泛存在于各个软件应用中。任何移动应用和系统都离不开数据库进行存储数据,而数据的复杂性给它们的开发带来了困难和挑战。
在现实生活中,社会现实中的万事成物都是一个动态系统。随着时间的推移和事情的发展,各种实体都会发展变化,具体体现在实体属性的变化上,因此,我们称之为实体的动态属性[1]。例如,在一款银行绩效考核系统中的客户经理实体,随着业务的发展,客户经理的其考核内容也会发生变化,会有存款业绩、贷款业务、基金业绩、是否投诉等不断增加,也会产生相对应的业绩数值,这些不断业绩都称为该客户经理实体的动态性,详情如表1客户经理实体2017年1月份业务需求表所示。
在实际的项目开发中,固定数量的、明确的实体属性,有利于软件设计与开发人员进行项目开发。但是,动态属性的实体,由于实体属性的个数未知,属性名称未知,在系统运行过程中,根据业务的需要,随时增添新的属性,因此,给项目开发人员带来了困难和挑战。笔者在数据库设计方面经过长期的实践,探索出了针对该问题的实体的动态属性在数据库设计中的解决方法,希望对有相同需要的数据库设计人员或软件开发人提供一点参考价值。
2 定义相关数据结构
数据库中的数据结构与数据对象的数据类型、内容、性质有关的,是对数据对象的一个静态描述。为了便于说明,还以上述绩效考核系统中的客户经理实体为例进行描述。该客户经理实体包括存款业绩、贷款业务、基金业绩、是否投诉等属性,其在关系数据库中可以定义成相关字段,具体详细结构描述如下:
Create Table ClientManager(
CName nvarchar(50), //姓名字段
CDeposit decimal(18, 2), //存款业绩字段
CLoan decimal(18, 2), //贷款业绩字段
CFund decimal(18, 2), //基金业绩字段
CIsComplain nvarchar(2), //是否投诉字段
... //未知属性字段
)
很显然,由于实体未知属性的存在,上述结构中的字段不明确,这样的设计在目前的数据库技术中不能得以实现。
3 关系数据库中实体的设计方法
目前,市场要流行的关系型数据库门类众多,有甲骨文公司的Oracle、MySQL,有微软公司的SQL Server,还有针对移动应用的SQLite。下面针对上述实体的动态属性问题,给出两种关系型数据库的解决方法。
3.1 采用改行为列
为了改变上述字段不明确的问题,从表1中可以看出是二维表中的字段不明确,采用以行来代替列的形式,就可以把未知的列的值作为一条记录存储于表中,这样,就可以根据需求动态满足字段的增加或减少,解决该问题。但是,这样需要解决两个问题,一个是属性名的问题和另一个属性值的问题。因此,行转为列的形式中,二维表中需要属性名和属性值两列。具体的在客户经理实体中,定义为经理姓名、业绩名称和业绩额,具体详细结构描述如下:
Create Table ClientManager(
CName nvarchar(50), //经理姓名
CAchieveName nvarchar(50), //业绩名称字段
CAchieveValue nvarchar(50) //业绩额字段
)
在关系数据库中,客户经理的实体二维表中的业绩和业绩额从以行的形式转为以列的形式,但是,表中的记录数据增加,其具体形式如表2客户经理实体行转成列后的样式表所示。
3.2 采用两个关系实体
采用行转为列的方式能够适应简单属性值全都一个数据类型的动态属性的问题,比如,例子中的业绩额全为数值类型,开发人员在进行开发实现功能时可以进行统一计算。但是,如果属性不是一个统一的类型,比如例子中的业绩额有数值类型的,还有字符类型的。这种情况下,程序开发人员,在进行数据取值时,要有目的的进行运算,而在例子中属性值的数据类型不明确,给开发人员带来了麻烦。解决这种复杂的情况,可以增加一个实体表对属性值的取值详细信息进行描述,而将在该实体中将上一个实体的属性名作为外键,这样,就能够保证数据的一致性。在例子中,在客户经理实体的基础上,增加一个业绩设置实体,其字段有业绩名称、业绩额的取值类型、业绩额的取值长度、业绩额的取值精度,具体表述所下:
Create Table AchieveSet(
AchieveName nvarchar(50), //业绩名称字段
AValueDataType nvarchar(50), //业绩额的取值类型
AValueLength int, //业绩额的取值长度
AValuePrecision int //业绩额的取值精度
)
综上所述,通过行转列的方式,解决属性值同一类型的动态属性问题;通过两个实体来解决属性值非同一类型的复杂的动态属性问题。程序开发人员可以根据不同的需求,采用不同的方法对系统进行开发。
4 非关系数据库实体的设计方法
随着技术的发展,对半结构化、非结构化的数据进行处理,出现了NoSQL数据管理技术的发展。下面结合非关系数据技术,给出两种解决动态属性问题的解决方法。
4.1 采用HBase模型
HBase是一个分布式的,面向列族进行存储的数据库[4]。在HBase数据库中,动态属性可以采用它的数据模型来进行实现。定义一个属性列族,而在该列族中根据需要可以任意动态放入子列即可。具体操作是定义一个客户经理实体,在该实体中创建一个业绩列族,通过行键来存储客户经理实体记录中的经理名称,具体描述如下:
create ‘ClientManager,'CAchieve'
其中,ClientManager是客户经理实体,'CAchieve'是客户经理的业绩。
实体表创建完成后,可以进行操作,进行存储记录数据,其操作如下:
put 'ClientManager','张三','CAchieve:存款业绩','10000'
put 'ClientManager','张三','CAchieve:是否投诉','是'
put 'ClientManager','李四','CAchieve:基金业绩','10500'
...
其中,张三、李四列使用的是HBase行键,'CAchieve'冒号后面是动态属性。
4.2 采用MongoDB模型
MongoDB數据库是采用文档、集合和数据库三部分来对数据进行组织[5]。在MongoDB数据库中,动态属性可以采用它的数据模型来实现,根据其文档的机制来进行实现。在例子中,采用定义一个客户经理实体的集合,在集合中插入定义好的记录文档,具体操作如下:
db.createCollection("'ClientManager'"); //定义客户经理集合
db.ClientManager.insert({"name":"李四","存款业绩":10000",是否投诉":是})
db.ClientManager.insert({"name":"李四","基金业绩":11000,"是否投诉":是})
其中,大括号{}内的数据是文档信息,存储客户经理信息,而每一键值对记录该客户经理实体的绩效信息,比如,"存款业绩":10000"等。每个文档内中的键值对中的键可以不相同,这样,就达到了实现动态属性的要求。
5 总结
截止到目前为止,关系型数据库理论和非关系型数据库理论并存,而且他们都已经发展得很成熟,在市场上广泛应用。作者从实际开发一款绩效考核系统中,考核指标不断变化的实际需求出发,调研和总结当前市场上几种处理实体属性不断变化的解决方案。根据不同的方案可选择不同的数据库技术,在开发实施过程中需要相应的技术条件和设备条件。总之,希望给后来者的学习和工作提供一些建议和帮助。
参考文献:
[1] 唐小刚,谭石强.一种实体属性非确定的关系数据库设计方法[J]. 湘南学院学报,2006(4).
[2] 李华娟.关系型数据库设计之实践技巧[J].电子技术与软件工程,2016(1).
[3] 李长春.动态字段在VFP中的设计与实现[J].计算机时代,1999(7).
[4] Lars George. HBase权威指南[M].人民邮电出版社,2013.
[5] 邹贵金. MongoDB管理与开发实战详解[M].中国铁道出版社,2013.