后台:专业工具开发人员。 SQL / DB业余爱好者。
设置: .Net 3.5 winforms app与MS SQL Server 2008交谈。
场景:我使用从大量文件中提取的信息填充数据库。这相当于大约60M条记录,每条记录都有一个与之相关的任意大小的消息。我最初的计划是记录中的 nvarchar(max)字段来保存消息,但是在对数据子集执行测试运行之后,这将使数据库过大(推断为一个不可接受的113GB)。在这个初始测试数据集(1.3GB数据库)上运行一些查询我发现有大量的消息重复,我们可以使用它来将消息数据缩小到大约六分之一。我已经尝试并想到了一些实现这一目标的方法,但没有一个是令人满意的。我现在已经搜索了几天但是a)似乎没有一个好的答案(不太可能),或者b)我不知道如何表达我需要的东西(更有可能)。< / p>
考虑/尝试的方法:
第三种方法相当于创建字符串字典表。经过几次关于这个想法的迭代后,我得到了以下结论:
存储过程遍历一批传入记录,并为每条消息进行迭代:
我。对于现有的消息实例,检查(SELECT)消息字典表。
II。如果找到,请记住现有消息的ID。
III。如果未找到,请插入新的消息记录,记住新记录的ID(OUTPUT)。
所有消息(旧的和新的)的ID都作为该过程的输出结果集返回。
的问题:
在我看来,我正在尝试对数据进行某种规范化,但从我对数据库设计的理解来看,这更像是“行规范化”而非正确的规范化,这与“列规范化”有关。令我感到惊讶的是,这并不是所有需要相应支持的地方。
所以,我的问题是:这里的方法是什么?
非常感谢任何帮助。
萨姆
答案 0 :(得分:2)
Sam,我认为你正在使用方法#5 。而且我真的认为实施起来并不像你想象的那么复杂。本地生成的消息哈希很容易生成,它可以大大加快所有查找速度(在数据库上)。
当然,如果消息确实需要nvarchar(max)
。如果你可以用更少的空间(我认为nvarchar
为512)而不是你可以在SQL中使用唯一性约束和列中的索引来使搜索速度更快 - 绝对是我的建议,如果你认为你可以减少消息长度。
如果您使用消息哈希方法,我相信您也可以使用一种聪明的技术来加快速度。使用批量插入将所有记录插入数据库,而不必担心重复的消息。之后,您可以编写一个非常简单的查询来清除重复消息的消息表,然后继续强制执行唯一约束。
答案 1 :(得分:1)
您的文章中有解决方案。对于像nvarchar(max)这样的大数据,您需要减少搜索集 - 正如您所说:
添加额外(索引)哈希列 消息表并提交 具有相应的消息(本地 生成)哈希值。搜索这个 缩小消息 实际上需要测试。 - 复杂,必须有一个更好的 方式。
这是解决问题的方法。
或者如果您不想处理哈希值,请将前150个字符作为哈希值(例如varchar(150)),使用它来减少对重复项的搜索。它不会像hash,但取决于你的数据,它可能会工作。(你也可以使用75个第一个字符和75个最后的字符。)一些数据测试应该显示哪些区域是最独特的子字符串。
答案 2 :(得分:1)
归一化有两个实际方面(和原因):数据安排的敏感性(以及相应的维护保障)和性能。
关于敏感性,至少从抽象的数据库设计角度来看,您需要考虑的一个问题是数据是否真正重复。虽然您可能有两条具有相同数据的消息,但实际上它们可能并不代表“相同的东西”。真正的问题是:两条消息共享相同文本的事实是否会使它们成为相同的消息?换句话说,假设消息A和消息B共享相同的文本,您是否希望更改消息A将反映在消息B中?
如果您的回答是“是”,那么您的字符串字典是正确的方法。如果不是,那么确实没有重复的数据,只有看起来相同但不相同的数据。
从性能的角度来看,我可能认为带有附加消息哈希的字符串字典是最好的方法;我认为这并不像你认为的那么复杂。几乎所有语言(包括T-SQL)都提供标准哈希算法,在这种情况下,我不会认为冲突的可能性甚至哈希值的分布是非常重要的,因为你只是将它用作“提示“加快查询的执行速度。