小编Pau*_*ott的帖子

有效地存储具有截然不同的键的键值对集

我继承了一个应用程序,它将许多不同类型的活动与一个站点相关联。大约有 100 种不同的活动类型,每一种都有不同的 3-10 个字段集。但是,所有活动都至少有一个日期字段(可以是日期、开始日期、结束日期、预定开始日期等的任意组合)和一个负责人字段。所有其他字段差异很大,开始日期字段不一定称为“开始日期”。

为每个活动类型制作一个子类型表将导致一个包含 100 个不同子类型表的模式,这将过于笨拙而无法处理。该问题的当前解决方案是将活动值存储为键值对。这是当前系统的一个大大简化的架构,可以理解这一点。

在此处输入图片说明

每个Activity有多个ActivityFields;每个 Site 有多个 Activity,SiteActivityData 表存储每个 SiteActivity 的 KVP。

这使得(基于 Web 的)应用程序非常容易编写代码,因为您真正需要做的就是遍历 SiteActivityData 中给定活动的记录,并为表单的每一行添加一个标签和输入控件。但是有很多问题:

  • 诚信不好;可以在 SiteActivityData 中放置一个不属于活动类型的字段,而 DataValue 是一个 varchar 字段,因此需要不断转换数字和日期。
  • 对这些数据进行报告和临时查询很困难、容易出错且速度缓慢。例如,获取结束日期在指定范围内的某种类型的所有活动的列表需要数据透视并将 varchars 转换为日期。报告作者讨厌这种模式,我不怪他们。

所以我正在寻找一种方法来存储大量几乎没有共同字段的活动,从而使报告更容易。到目前为止,我想出的是使用 XML 以伪 noSQL 格式存储活动数据:

在此处输入图片说明

Activity 表将包含每个活动的 XSD,从而无需 ActivityField 表。SiteActivity 将包含键值 XML,因此站点的每个活动现在都在一行中。

一个活动看起来像这样(但我还没有完全充实它):

<SomeActivityType>
  <SomeDateField type="StartDate">2000-01-01</SomeDateField>
  <AnotherDateField type="EndDate">2011-01-01</AnotherDateField>
  <EmployeeId type="ResponsiblePerson">1234</EmployeeId>
  <SomeTextField>blah blah</SomeTextField>
  ...
Run Code Online (Sandbox Code Playgroud)

好处:

  • XSD 将验证 XML,捕获错误,例如在数据库级别将字符串放入数字字段中,这对于将所有内容存储在 varchar 中的旧模式来说是不可能的。
  • 用于构建 Web 表单的 KVP 记录集可以很容易地使用 select ... from ActivityXML.nodes('/SomeActivityType/*') as T(r)
  • XML 的 xpath 子查询可用于生成包含开始日期、结束日期等列的结果集,而不使用数据透视表,例如 select ActivityXML.value('.[@type=StartDate]', 'datetime') as StartDate, …

schema database-design sql-server-2012 reporting

9
推荐指数
1
解决办法
2646
查看次数