数据库设计来计算不同的值

时间:2018-01-31 09:49:35

标签: c# sql-server database-design database-normalization

我想跟踪我的应用程序中的不同方面。客户端向服务器报告这些方面。客户端按以下格式报告数据:

AspectReport
  ClientId int, //client that reported the apsect
  AspectId int, //aspect that we got a value for
  Value string  //arbitrary string

可以使用相同或不同的值多次报告相同的方面。

在服务器端,我只想跟踪每个客户端和方面的unqiue值。因此,我需要能够存储已报告的值以及来自哪个客户端。

标准化结构可能看起来像:

Aspect
  Id
  Name

// used to store all reported values for 
// the aspect, no matter which client reported it
// (each client can report a subset of all values)
ApplicationAspectValues   
  Id
  AspectId 
  Value

// Which unique values a specific client reported
ClientAspectValues
  Id
  ClientId
  AspectId
  Value

可能有数以千计的客户(我们最大的客户迄今已有20 000个客户),可以针对少数几个方面报告每个方面数千个值。

写入的频率更高。从长远来看,我预计每秒会报告几百个方面。每天最多使用几次读取(对于客户端)。

很少使用方面值。仅在更深入地分析系统时显示报告的值(Web应用程序)。相反,这些值通常用于计算为每个方面和客户端(ClientValues.Count / ApplicationValues.Count)报告的值的百分比,并确保仅存储唯一值。

遵循3NF意味着每次收到新方面时都会查询和更新几行,这似乎有点低效。

是否有更好的设计允许:

  • 优化写入
  • 确保只存储唯一值
  • 允许偶尔检索客户端/方面的所有值(显示给用户)。

我天真的实现是在代码中执行重复检查,然后将一个gzip压缩的逗号分隔字符串与ApplicationAspectValuesClientAspectValues中的所有值以及Counter字段一起存储。

像这样:

ClientAspectValues
  Id
  ClientId
  AspectId
  NumberOfUniqueValues
  Values

这样,只有一行用于检查重复项并更新报告的值。对于大多数读取方案,永远不会获取值。

我确定有更好的解决方案吗?

这个问题发布在这里,因为结合代码和数据库的解决方案非常好

(我们的产品中有几个其他功能可以以相同的频率写入数据库,优化不仅仅是为了适应这个功能,而是为了完整的图片)

2 个答案:

答案 0 :(得分:1)

我会使用您的3NF设计,但使用表ClientAspectValue存储所有新写入。

然后,我将创建一个定期读取ClientAspectValue的批处理,获取唯一值,并将它们存储到专用表中 - ClientAspectUniqueValues。

答案 1 :(得分:0)

架构设计:

规范化结构应如下所示:

Client
  Client_ID        Primary Key
  Other_Columns....


Aspect
  Aspect_Id        Primary Key
  Name


ApplicationAspectValues   
  AAV_Id           Primary Key
  Aspect_Id        Foreign Key       
  Value                         Unique Constraint on Aspect_Id &  Value


ClientAspectValues
  CAV_Id            Primary Key
  Client_Id         Foreign Key
  AAV_Id            Foreign Key
  Reported          Time Stamp

现在在ClientAspectValues上创建一个视图来动态计算Distinct值,不要将不同的值存储在任何地方,保持更新会很痛苦,实际上有点不可能。

不要担心添加的行数,请考虑存储您可能需要的所有信息(尤其是报告的时间戳)。

还与商家讨论并要求提供某种保留期,例如6个月或一年。

每晚清除旧数据(早于业务决定的保留期限),将其用于某种数据仓库以进行报告。