我有一个基于用户交互(而不是用户输入)发送数据的应用程序。发送的数据可以是整数、字符串、日期或 bool 值。有140把 key 。我们一次可能会获取 1 个到全部 140 个键值对。
我们想要存储所有内容,但只会在应用程序中使用 140 个 key 中的 20 个。剩余的将用于稍后的审计跟踪 - 因此我们仍然需要存储它们。
应用程序使用此数据来决定用户需要去哪里,因此它需要通过学生 ID 访问记录并在几毫秒内提取 20 个左右的选项。可能有数十亿行数据(这是对拥有超过 20,000 个用户的现有应用程序的升级),因此性能至关重要。用户每次访问应用程序时都会生成一个新行。
示例数据:
Score:1
ID:3212
IsLast:False
Action:Completed
我对如何做到这一点有两个想法,并寻求一些帮助来确定哪个是最好的,或者第三个选项是更好的选择。
选项 1:
我的第一个想法是使用值的列作为字符串,然后在需要对值进行强制转换以供使用时使用可能的数据类型的查找表。
value | dataType
-----------------------
"1" | int
"Completed" | string
虽然发送的数据不是用户生成的,但我知道此方法中一定存在问题。这样做的唯一原因是我们不知道将发送什么 key:pair(在日期和 id 之外)并试图避免超过几列。
SO问题 How to Handle Unknown Data Type in one Table 使用类似的想法。
选项 2:
另一种解决方案是拥有 140 列 - 每个键对应一列。然而,生成的数据量非常大(数十亿行),因此调用这些数据的速度不够快 - 我不认为。
技术细节: 这是使用 SQL Server 2008 - 而不是带有 DotNet C# 和 Reporting Services 的 R2。
我在这里遗漏了什么 - 创建此表以提高性能的最佳方法是什么?
最佳答案
垂直分段您的数据。将导航控制所需的 20 个键放在一张表中,所有 20 个键放在一行中,并使用 PK 来标识用户交互(调用它,InteractionId
)。将其他 120 个值放入另一个表中,使用复合主键,基于第一个表的 PK(InteractionId
,加上标识 120 个可能的键值中的哪一个的 KeyTypeId
)值的对。将第二个表中的所有值存储为字符串。在名为 KeyTypes
的第三个查找表中,存储 KeyTypeId
、KeyTypeName
和 KeyValueDataType
让您的代码知道如何转换字符串值以将其正确输出为字符串、日期时间、整数或十进制值或其他值...
第一个表将被更频繁地访问,因此它仅包含应用程序的导航功能需要更频繁访问的那些值,使行保持更窄,这允许每页更多行,并最大限度地减少磁盘 IO。将所有 20 个值放在一行中将使行计数保持较小(约 1/20),从而最小化每次访问需要执行的索引查找深度。
包含所有其他 120 个键值的另一个表不会被频繁访问,因此它的结构可能可以针对逻辑简单性而不是性能进行优化。
关于sql - 大量行的表设计选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2327218/