我有一个基于用户交互(而不是用户输入)发送数据的应用程序。发送的数据可以是整数,字符串,日期或布尔值。有140把钥匙。我们可以一次从1个键值对到任何140个。
我们希望存储所有内容,但只使用应用程序中的140个密钥中的20个。其余的将在稍后用于审计跟踪 - 所以我们仍然需要存储它们。
应用程序使用此数据来决定用户需要去哪里,因此需要按学生ID访问记录,并在几毫秒内提取20个左右的选项。可能有数十亿行数据(它是对具有超过20,000个用户的现有应用程序的升级),因此性能至关重要。用户每次访问应用程序时都会生成一个新行。
示例数据:
Score:1
ID:3212
IsLast:False
Action:Completed
我有2个关于如何做到这一点的想法,并寻找一些最好的帮助,或者是第三个选择更好的选择。
选项1:
我的第一个想法是使用值作为字符串的列,然后有一个查找表,列出在需要使用Cast进行使用时可能使用的数据类型。
value | dataType
-----------------------
"1" | int
"Completed" | string
虽然发送的数据不是用户生成的,但我知道在这种方法中某处必须存在问题。这样做的唯一原因是我们不知道哪个密钥:对将被发送(在日期和id之外)并且试图避免多个列。
SO问题 How to Handle Unknown Data Type in one Table使用了类似的想法。
选项2:
另一种解决方案是拥有140列 - 每个键一列。但是,生成的数据量非常大(数十亿行),因此调用此数据的速度不够快 - 我不这么认为。
技术细节 这是使用SQL Server 2008 - 而不是使用DotNet C#和Reporting Services的R2。
我在这里遗漏了什么 - 为表现创建此表的最佳方法是什么?
答案 0 :(得分:6)
垂直分段您的数据。将导航控制所需的20个密钥放在一个表中,所有20个在一行中,用PK标识用户交互(Callit说,InteractionId
)。根据第一个表(InteractionId
的PK加上KeyTypeId
标识其中120个可能的键值对中的哪一个,将其他120个值放在具有复合主键的另一个表中。将第二个表中的所有值存储为字符串。在第三个名为KeyTypes
的查找表中,存储KeyTypeId
,KeyTypeName
和KeyValueDataType
以允许您的代码知道如何转换字符串值以正确输出它作为字符串,日期时间,整数或小数值或其他...
第一个表将被更频繁地访问,因此它仅包含应用程序的导航功能需要更频繁访问的那些值,保持行更窄,这允许每页更多行,并最小化磁盘IO。将所有20个值放在一行中将使行数保持较小(大约1/20),从而最小化需要为每次访问执行的索引搜索的深度。
包含所有其他120个键值的另一个表将不会被频繁访问,因此它的结构可能会针对逻辑简单而非性能进行优化。
答案 1 :(得分:2)
实际上,您可能会合并到目前为止提供的建议:
创建一个表,其中包含导航控制所需的20个键,以及一个主键列和一个XML数据类型列,用于存储其余可能的数据。然后,您可以创建一个DTD来处理每个键的数据类型,并根据需要加上对某些键的约束。
答案 2 :(得分:1)
它应该足够简单来测试这两个想法,但选项1的变体看起来对我很有帮助。像SQL Server这样的RDBMS更喜欢长而窄的表(即列数较少但行数很多)。
我不会再进一步了,因为看来Charles已经打败了它,并提出了一个非常明智的建议。