数据库设计之EAV(实体、属性、值),eav实体
有这么一个业务,用于客户记录每天做的事情,由于是非常专业的事情,需要专业的记录本,这种记录本有20多种。实际工作中也是有20多样的记录本,记录本的格式每隔一年会有点变动。如何进行数据库设计?
有两种方案:
1.为每个记录本建单独的表。
2.动态表,把记录本的属性放入到字典中,记录本的内容以实体、属性、值的形式存储。
--存储记录本的格式
createtable note_dictionary
(
dictionary_idnumber,
dictionary_typevarchar2(50),--记录本的类型,就是那20多种记录本
dictionary_namevarchar2(200)--记录本中的名称
);
--存储记录本的内容
createtable note_content
(
content_idnumber,
note_id number,--具体的一个记录本的id
dictionary_idnumber,--记录本中字段的id
contentvarchar2(1000)--字段的内容
);
如果只是从开发人员的角度来看,会选择方案2。方案1工作量多大啊,每次改记录本的格式都要做调整,方案2都有扩展型啊,调整格式都不需要改代码,区区2张表解决了20多张表的问题,多酷。毫无争议的选择方案2。
选择方案2后,会牺牲很多传统数据库设计代码的好处,如果记录本之前是有关系的,实现会变得更复杂。
1.记录本中的字段类型无法制定,如果是Date和number,只能用varchar2表示。关于类型选择不正确会造成什么问题,在我之前的blog中有写到。再者统计也可能出现问题,即使你前段控制的再好,也不能保证最后到数据库中后的是正确的,这个问题看到的太多了。
2.不能加not null的约束和默认值。
3.如果要查某个记录本的a字段,需要先去找字典,然后再到内容表中去找,不直观,涉及到后期维护数据较麻烦。
4.如果记录本之间是有关系,要建立关联关系,需要再加表,实现很复杂。
5.在一段时间后内容表会变得非常之笨重,系统中就属它数据量大。
6.我以前维护过这种设计代码,因为是通用的,有时候改了这里,也不知道会不会影响其他的地方。Java代码中使用了反射,debug很难调试,问题难定位。总体来说,有一种身不如死的感觉。
7.所有复杂一点的查询都会变得复杂。
上面的模块我倾向选择方案1,开发工作量大一点,但维护工作量小,数据更加精准。那是不是一定不要用方案2呢?也不是,业务,业务,还是业务,如果你的单据不需要统计分析,数据量也不大,单据种类非常多,开发人员水平很高,你想要做到记录本可配置,那可以选择方案2。如果你不详细了解业务的情况下,坚持选择方案2,你必须承担我上述说的风险。
什么意思,学生是一个实体,课程是一个实体;学生的学号是属性,课程的名称是属性;学生的选课记录是关系。你应该不是问的这个吧。
简单的说:单值属性就是只能是一个值
多值属性可以有一个或者两个以上的值
举个考试的例子:
设有员工实体Employee (employeeID, name, sex, age, tel, departID),其中employeeID为员工号,name为员工姓名,sex为员工性别,age为员工年龄,tel为员工电话,记录该员工的手机号码、办公室电话
(1) A.name,可以用employeelD可以区别
B.sex,可以不作任何处理
C.tel,可以将tel加上employeeID独立为一个实体
D.tel,可以强制只记录一个电话号码
tel 为多值属性,因为它可以是手机号码,也可以是办公室电话!!
属性:
属性和分类单独进行定义。每一个属性仅仅定义一次,但是可以在多个分类中使用。例如,“Description”(描述)属性可以使用在多个分类中,但是只需在架构中定义一次即可,以保持数据的一致性。
属性用来描述对象。每一个属性都拥有它自己的定义,定义则描述了特定于该属性的信息类型。架构中的每一个属性都可以在“Attribute-Schema”分类中指定,该分类决定了每一个属性定义所必须包含的信息。
能够应用到某个特殊对象上的属性列表由分类(对象是该分类的一个实例)以及对象分类的任何超类所决定。属性仅仅定义一次,但是可以多次使用。这确保了共享同一个属性的所有分类能够保持一致性。
多值属性
属性可以是单值的也可以是多值的。属性的架构定义指定了属性的实例是否必须是多值的。单值属性的实例可以为空,也可以包含一个单值。多值属性的实例可以为空,也可以包含一个单值或多值。多值属性的每一个值都必须是唯一的。
索引属性
索引应用于属性,而不是分类。对属性进行索引有助于更快地查询到拥有该属性的对象。当您将一个属性标记为“已索引”之后,该属性的所有实例都会被添加到该索引,而不是仅仅将作为某个特定分类成员的实例添加到索引。
添加经过索引的属性会影响Active Directory的复制时间、可用内存以及数据库大小。因为数据库变得更大了,所以需要花费更多的时间进行复制。
多值属性也可以被索引。同单值属性的索引相比,多值属性的索引进一步增加了Active Directory的大小,并且需要更多的时间来创建对象。在选择需要进行索引的属性时,请确信所选择的共用属性,而且能够在开销和性能之间取得平衡。
一个经过索引的架构属性还可以被用来存储属性的容器所搜索,从而避免了对整个Active Directory数据库进行搜索。这样不仅缩短了搜索所需花费的时间,而且减少了在搜索期间需要使用的资源数量。