计算不同值的数据库设计
database design to count distinct values
我想跟踪我申请中的不同方面。这些方面由客户端报告给服务器。客户端上报数据格式如下:
AspectReport
ClientId int, //client that reported the apsect
AspectId int, //aspect that we got a value for
Value string //arbitrary string
同一方面可以用相同或不同的值报告多次。
在服务器端,我只想跟踪每个客户端和方面的唯一值。因此,我需要能够存储报告了哪些值以及来自哪个客户端。
标准化结构可能如下所示:
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 个客户)可以针对少数几个方面报告每个方面的数千个值。
写入比读取频繁得多。我预计在长 运行 中每秒有数百个方面的报告。每天最多使用几次读取(对于客户端)。
很少会用到纵横比值。仅在更深入地分析系统(网络应用程序)时显示报告值。相反,这些值通常用于计算为每个方面和客户 (ClientValues.Count / ApplicationValues.Count
) 报告的值的百分比,并确保仅存储唯一值。
遵循 3NF 意味着每次收到新方面时都会查询和更新几行,这似乎有点低效。
是否有更好的设计允许:
- 优化写入
- 确保只存储唯一值
- 允许偶尔检索 client/aspect 的所有值(显示给用户)。
我天真的实现是在代码中进行重复检查,然后将一个 gzip 逗号分隔字符串与所有值一起存储在 ApplicationAspectValues
和 ClientAspectValues
的列中以及一个 Counter 字段中。
像这样:
ClientAspectValues
Id
ClientId
AspectId
NumberOfUniqueValues
Values
这样一来,只有一行用于检查重复项和更新报告值。对于大多数读取场景,永远不会获取值。
我确定有更好的解决方案?
这个问题发布在这里是因为结合代码和数据库的解决方案非常好
(我们的产品还有其他几个以相同频率写入数据库的功能,优化不仅仅是为了适应这个功能,而是为了完整的画面)
我会使用您的 3NF 设计,但使用 table ClientAspectValue 来存储 所有 新写入。
然后,我会创建一个批处理,定期读取 ClientAspectValue ,获取唯一值,并将它们存储到专用的 table - ClientAspectUniqueValues.
架构设计:
规范化结构应如下所示:
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 上创建一个视图以动态计算不同的值,不要将不同的值存储在任何地方,保持它们更新会很痛苦,实际上有点不可能。
不要担心添加的行数,考虑存储您以后可能需要的所有信息(尤其是报告的时间戳)。
还与企业讨论并要求某种保留期,比如 6 个月或一年。
每晚将旧数据(早于企业决定的保留期)清除到某种数据仓库以用于报告目的。
我想跟踪我申请中的不同方面。这些方面由客户端报告给服务器。客户端上报数据格式如下:
AspectReport
ClientId int, //client that reported the apsect
AspectId int, //aspect that we got a value for
Value string //arbitrary string
同一方面可以用相同或不同的值报告多次。
在服务器端,我只想跟踪每个客户端和方面的唯一值。因此,我需要能够存储报告了哪些值以及来自哪个客户端。
标准化结构可能如下所示:
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 个客户)可以针对少数几个方面报告每个方面的数千个值。
写入比读取频繁得多。我预计在长 运行 中每秒有数百个方面的报告。每天最多使用几次读取(对于客户端)。
很少会用到纵横比值。仅在更深入地分析系统(网络应用程序)时显示报告值。相反,这些值通常用于计算为每个方面和客户 (ClientValues.Count / ApplicationValues.Count
) 报告的值的百分比,并确保仅存储唯一值。
遵循 3NF 意味着每次收到新方面时都会查询和更新几行,这似乎有点低效。
是否有更好的设计允许:
- 优化写入
- 确保只存储唯一值
- 允许偶尔检索 client/aspect 的所有值(显示给用户)。
我天真的实现是在代码中进行重复检查,然后将一个 gzip 逗号分隔字符串与所有值一起存储在 ApplicationAspectValues
和 ClientAspectValues
的列中以及一个 Counter 字段中。
像这样:
ClientAspectValues
Id
ClientId
AspectId
NumberOfUniqueValues
Values
这样一来,只有一行用于检查重复项和更新报告值。对于大多数读取场景,永远不会获取值。
我确定有更好的解决方案?
这个问题发布在这里是因为结合代码和数据库的解决方案非常好
(我们的产品还有其他几个以相同频率写入数据库的功能,优化不仅仅是为了适应这个功能,而是为了完整的画面)
我会使用您的 3NF 设计,但使用 table ClientAspectValue 来存储 所有 新写入。
然后,我会创建一个批处理,定期读取 ClientAspectValue ,获取唯一值,并将它们存储到专用的 table - ClientAspectUniqueValues.
架构设计:
规范化结构应如下所示:
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 上创建一个视图以动态计算不同的值,不要将不同的值存储在任何地方,保持它们更新会很痛苦,实际上有点不可能。
不要担心添加的行数,考虑存储您以后可能需要的所有信息(尤其是报告的时间戳)。
还与企业讨论并要求某种保留期,比如 6 个月或一年。
每晚将旧数据(早于企业决定的保留期)清除到某种数据仓库以用于报告目的。