C# 计算不同值的数据库设计

C# 计算不同值的数据库设计,c#,sql-server,database-design,database-normalization,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值。因此,我需要能

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

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
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
可能有数千个客户(我们最大的客户到目前为止有20000个客户)可以为少数几个方面的每个方面报告数千个价值

写比读要频繁得多。从长远来看,我预计每秒会有数百个方面的报告。每天最多使用几次读取(对于客户端)

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

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

是否有更好的设计允许:

  • 优化写入
  • 确保只存储唯一的值
  • 允许偶尔检索(向用户显示)客户端/方面的所有值
我的简单实现是执行重复的检入代码,然后在
applicationspectvalues
clientspectvalues
中的列中存储一个以逗号分隔的gzip字符串以及一个计数器字段

像这样:

ClientAspectValues
  Id
  ClientId
  AspectId
  NumberOfUniqueValues
  Values
这样,只有一行用于检查重复项和更新报告值。对于大多数读取场景,永远不会获取值

我确信有更好的解决方案

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


(我们的产品中还有其他几个以相同频率写入DB的功能,优化不仅仅是为了适应此功能,而是为了完整的画面)

我将使用您的3NF设计,但使用table ClientSpectValue存储所有新写入

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

架构设计:

规范化结构应如下所示:

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
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
现在在ClientSpectValues上创建一个视图,以便动态计算不同的值,不要将不同的值存储在任何地方,保持这些值的更新将是一件痛苦的事情,实际上有些不可能

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

同时与业务部门进行讨论,要求提供某种保留期,例如6个月或一年


出于报告目的,每晚将旧数据(比业务部门决定的保留期更早的数据)清除到某种数据仓库中

如果只需要唯一的值,则将该值设为主键。数据库将不允许重复。另一个选项是,将唯一值存储在c#缓存中,并检查该缓存是否存在,然后只需要在不在缓存中的情况下插入到表中,并在插入新特性时清除缓存。应该减少数据库的负载。这实际上是一个很好的解决方案。添加入站值时,根本不需要查询。一个查询就足以找到新的唯一值(使用左连接)。为了清晰起见,我将第一个表命名为
InboundPartitionValues
,并保留了其他表名。