我面临以下问题。我有一张非常大的桌子。此表是以前参与该项目的人员的遗产。该表位于MS SQL Server中。
该表具有以下属性:
正如您可能猜到的,无法对此表运行任何合理的查询。现在人们只在表中插入新记录,但没有人使用它。所以我需要对其进行重组。我计划创建一个新结构,并使用旧表中的数据重新填充新结构。显然,我将实施分区,但这不是唯一要做的事情。
该表最重要的特征之一是那些纯文本字段(即它们不必转换成另一种类型)通常具有频繁重复的值。因此,给定列中的实际值的变化范围为5-30个不同的值。这导致了进行规范化的想法:对于每个这样的文本列,我将创建一个附加表,其中包含可能出现在此列中的所有不同值的列表,然后我将在此附加表中创建一个(tinyint)主键,然后将在原始表中使用适当的外键,而不是将这些文本值保留在原始表中。然后我将在这个外键列上放一个索引。以这种方式处理的列数约为100。
提出了以下问题:
抱歉这么长的文字。
感谢您的评论!
PS 我创建了一个关于加入100个表的相关问题; Joining 100 tables
答案 0 :(得分:6)
除了针对它运行的查询的速度之外,您还会发现规范化数据的其他好处......例如大小和可维护性,这本身就足以证明它的正常化......
但是,它也可能提高查询速度;当前包含300个文本列的单行非常庞大,几乎可以肯定超过8,060 byte limit for storing the row data page ...而是存储在ROW_OVERFLOW_DATA
或LOB_DATA
分配单元中。
通过规范化减少每行的大小,例如用TINYINT
外键替换冗余文本数据,并且还将不依赖于此大表的主键的列移除到另一个表中,数据不应再溢出,并且您还可以在每页存储更多行。
通过执行JOIN
来获取规范化数据所增加的开销......如果正确索引表,则不应增加大量开销。但是,如果它确实增加了不可接受的开销,那么您可以根据需要选择性地对数据进行反规范化。
答案 1 :(得分:4)
这是否值得付出努力取决于价值的长短。如果值是,例如,状态缩写(2个字符)或国家/地区代码(3个字符),则结果表将比现有表更大。请记住,您需要包含引用表的主键。这通常是一个整数,占用四个字节。
还有其他充分理由这样做。使用具有有效值列表的引用表可保持数据库一致性。参考表既可用于验证输入,也可用于报告目的。可以包括附加信息,例如“长名称”或类似名称。
此外,SQL Server会将varchar列溢出到其他页面上。它不会溢出其他类型。您只有300列,但最终您的记录数据可能接近单页数据的8k限制。
而且,如果您决定继续,我建议您在列中查找“主题”。可能存在可以组合在一起的列组。 。 。详细的停止代码和停止类别,简短的公司名称和完整的公司名称。你正在走向数据建模的道路(一件好事)。但要谨慎处理非常低的事情(管理100个参考表),而不是确定一组合理的实体和关系。
答案 2 :(得分:2)
1)系统当前必须对非常大量的数据进行全表扫描,从而导致性能问题。优化的许多方面可以改善这种性能。将列转换为正确的数据类型不仅可以通过减小每条记录的大小来显着提高性能,还可以使数据正确。如果查询列,您当前正在查看与该字段中的文本进行比较的文本。只需索引,这可以改进,但是更改为查找将允许从足够小的表中查找ID值以保留在内存中,然后使用它来仅扫描整数值,这是一个更快的过程。 2)如果数据被标准化为第三范式或类似数据,那么您可以看到性能因数据完整性而受到影响的实例。如果引擎无法在不首先投影数据的情况下限制行,则这是最大的问题。但是,如果确实发生了这种情况,执行计划可以识别这一点,并且可以修改查询以降低这种可能性。
另一点值得注意的是,听起来好像数据库结构合理,它可以在内存中缓存,因为数据量会大大减少。如果是这种情况,那么性能将会大大提高。
提高性能的快速方法可能是添加索引。但是,这将进一步增加整个数据库的大小,并且不能解决存储重复数据和可能的数据完整性问题的问题。
还可以进行一些其他更改 - 如果并不总是需要大量数据,则可以将其分离到相关表中,并仅根据需要进行查找。不用于查找其他表的字段是特定的候选字段,因为连接可以在一个小得多的表上,同时保留一个相当简单的结构,只有在您确定实际数据时才查找其他数据需要。这显然不是一个正确的规范化结构,但可能是一种快速而肮脏的方法来提高性能(在添加索引之后)。
答案 3 :(得分:1)