旧/坏:
该解决方案使得添加附加值在流体环境中是一个痛苦,因为表需要定期修改.
MyTable ============================ ID Key1 Key2 Key3 int int string date ---------------------------- 1 Value1 Value2 Value3 2 Value4 Value5 Value6
单表解决方案
该解决方案允许通过单个表进行简化.查询代码仍然需要检查空值来确定该字段正在存储的数据类型.也可能需要检查约束来确保只有一个值字段包含非空数据.
DataValues ============================================================= ID RecordID Key IntValue StringValue DateValue int int string int string date ------------------------------------------------------------- 1 1 Key1 Value1 NULL NULL 2 1 Key2 NULL Value2 NULL 3 1 Key3 NULL NULL Value3 4 2 Key1 Value4 NULL NULL 5 2 Key2 NULL Value5 NULL 6 2 Key3 NULL NULL Value6
多表解决方案
该解决方案允许更简洁地使用每个表,尽管代码需要事先知道数据类型,因为它需要为每个数据类型查询不同的表.索引可能更简单和更有效率,因为有更少的列需要索引.
IntegerValues =============================== ID RecordID Key Value int int string int ------------------------------- 1 1 Key1 Value1 2 2 Key1 Value4 StringValues =============================== ID RecordID Key Value int int string string ------------------------------- 1 1 Key2 Value2 2 2 Key2 Value5 DateValues =============================== ID RecordID Key Value int int string date ------------------------------- 1 1 Key3 Value3 2 2 Key3 Value6
你如何处理这个问题?哪个解决方案更好?
此外,如果密钥列分隔成一个单独的表,并通过外键引用,或者是否应该保留在值表中,如果由于某些原因导致密钥名称更改,批量更新?
解决方法
其次,您建议的是实体属性值(EAV)的变体. EAV的问题来自于数据完整性,报告,性能和维护.他们有他们的地位,但它们类似于药物:在有限的数量和狭窄的情况下使用它们可以是有益的;太多会杀了你
针对EAV撰写查询是一种承担.因此,如果要使用EAV,我看到它们的唯一情况是成功的是限制其使用,以便不允许任何人编写用于特定属性过滤的查询.也就是说,没有人会允许写一个类似于AttributeName =’Foo’的查询.这意味着您永远不能过滤,排序,计算,也不能将特定属性放在报表上的特定位置. EAV数据只是一袋分类数据,可以在报告上大量排出,但就是这样.我甚至看到人们将EAVs实现为Xml blob.
现在,如果您使用EAV,因为它只是一个数据块,我将使用单表方法.单表方法的一个重要优点是您可以添加一个检查约束,确保您在IntValue,StringValue或DateValue列中只有一个值.空值不会花费你太多,如果这只是数据,那么它的性能就不会有什么不同.此外,它将使您的查询更简单,您可以使用简单的case语句返回String,Integer或DateValue.
我可以看到多表方法的许多问题,其中最重要的是没有什么可以阻止相同的属性拥有多种类型的值(例如,IntegerValues中的行和StringValues中的一行).另外,要获取数据,您将始终使用三个左连接,这将使您的查询更麻烦地编写.
EAV的成本是纪律和警惕.在任何情况下,您的开发团队都必须遵守纪律,从不针对特定属性编写报告或查询.开发人员将从管理层获得很大的压力,“只是一次”,写出一些特定属性的过滤器.一旦你走下黑暗的道路,永远都会主宰你的发展和维护. EAV必须保持一大堆数据,没有更多.如果您不能在开发团队中保持这种纪律,那么我不会实施EAV.为了避免维护噩梦,我需要任何新的列的规范.一旦用户确实要过滤,计算或将属性放在报表上的特殊位置,该属性必须成为第一类列.如果您能够保持使用纪律,EAV可以很好地让用户存储他们想要的任何信息,并推迟您需要获取数据元素的规范的时间,直到用户以前面提到的方式使用该属性.