【问题标题】:TSQL checksum of large table [closed]大表的TSQL校验和[关闭]
【发布时间】:2019-01-18 07:17:15
【问题描述】:

这是我的问题的修改描述:

我在这里遇到了一种情况,我一直在尝试解决,但遇到了困难,想要不同的想法。

场景:数据文件在发生时从多个商店(交易)传输到总部。对于每个商店,桌子的大小都不错。在总部,同一张表包含来自所有商店的相同信息,这使得它变得巨大。数据通过文件传输,因为 HO 和商店之间没有任何直接连接。

我正在努力寻找一种方法,以确保来自每家商店的数据对总部的桌子来说是安全的。为此,我尝试对商店和 HO 之间应该匹配的字段进行校验和的 checksum_AGG ......但性能很差。我还尝试了特定数字列的总和,并在主机上对特定商店执行相同操作以进行比较,但性能似乎也很差。

我已经验证了索引的碎片,一切都很好。

理想情况下,我希望将商店中的所有数据逐行传输并与 HO 进行比较,但这是不可想象的,因为它太大了。

我正在寻找可以探索的想法,看看性能是否可以接受。这个想法是在商店中获取每个日期(商店/日期)的某种类型的表校验和,并在 HO 处执行相同的操作......然后比较这两个值......这意味着我只需要将每个存储和日期的校验和值传输到 HO。

任何想法都值得赞赏。

谢谢

【问题讨论】:

  • 这超出了本论坛的范围。也许试试 dba.stackexchange.com?
  • Ilya Bursov、Dave Cullum、Tab Alleman、Ivan Starostin、Mofi 我修改了我的问题的描述。

标签: sql-server tsql compare sql-server-2014 large-data


【解决方案1】:

为了比较行,我使用HASHBYTES。对于整个表,您可以使用行哈希的HASHBYTES

你需要这样的东西:

HASHBYTES('SHA2_512', CONCAT([ColA], [ColB], ..., ColZ]);

几个重要的注意事项:

  1. 您正在使用SQL Server 2014,正如文档中所说,您不允许使用MAX 值作为输入:

    对于 SQL Server 2014 (12.x) 及更早版本,允许的输入值限制为 8000 字节。

    因此,如果您有 max 长度类型,您最终可能会使用多个行哈希(组合部分上的不同列)或无法使用此技术。

  2. 您需要决定如何处理NULL 值和空字符串(如果存在)。

    例如,以下哈希相同,但我们的假想列之一是NULL,另一列是empty string

    SELECT HASHBYTES('SHA2_512', CONCAT(1, '', NULL, '')); --0x4DFF4EA340F0A823F15D3F4F01AB62EAE0E5DA579CCB851F8DB9DFE84C58B2B37B89903A740E1EE172DA793A6E79D560E5F7F9BD058A12A280433ED6FA46510A
    SELECT HASHBYTES('SHA2_512', CONCAT(1, '', '', ''));  --0x4DFF4EA340F0A823F15D3F4F01AB62EAE0E5DA579CCB851F8DB9DFE84C58B2B37B89903A740E1EE172DA793A6E79D560E5F7F9BD058A12A280433ED6FA46510A
    

    如果你不小心,事情可能会变得疯狂。例如,我有这样的情况(不同的列值,相同的哈希):

    SELECT HASHBYTES('SHA2_512', CONCAT(1, '', NULL, 2));  --0x5AADB45520DCD8726B2822A7A78BB53D794F557199D5D4ABDEDD2C55A4BD6CA73607605C558DE3DB80C8E86C3196484566163ED1327E82E8B6757D1932113CB8
    SELECT HASHBYTES('SHA2_512', CONCAT(1, '', 2, NULL));  --0x5AADB45520DCD8726B2822A7A78BB53D794F557199D5D4ABDEDD2C55A4BD6CA73607605C558DE3DB80C8E86C3196484566163ED1327E82E8B6757D1932113CB8
    

    这就是为什么最终在每个值之间使用分隔符。我正在使用CHAR(26),但你可以使用任何不是特殊的chars,只要你确定它没有在数据中使用。所以,最终的代码是:

    HASHBYTES('SHA2_512', CONCAT([ColA], CHAR(26), [ColB], CHAR(26), ..., CHAR(26), ColZ]);
    

基本上,您可以查找CLR 函数,该函数计算整个结果集的hash - 这将更难实现,但如果您熟悉.net,您就可以了。查看this创建SQL CLR函数的例子和官方docs


可能很难设置,但我使用Data Checksum 来创建单元测试。基本上这种类型的测试是内置的,所以环境准备好之后就可以使用了:

不好的是您需要预先计算校验和(例如使用您的源数据),然后更改 SQL 以查询您的新数据。不要认为它会非常适合您的需求。

谈到单元测试,你可以查看这个框架tSQLt - 我绝对不是粉丝,但可能有一些例程在结果集上执行checksum

【讨论】:

  • gotqn,谢谢...我一定会在我的实验室里试试这个,让你知道它是怎么回事。我不知道这一点。
  • Gotqn,看起来很有趣,但我希望每天每家商店汇总一个值。即对于一家商店,我每天将获得哈希字节值,在 HO 我将执行相同的功能,并且每个商店每天将获得一个值。我尝试使用它,但要在每个商店的每个日期获取一个值,我需要在 concat 中聚合数据以获得我需要的数据,这样做太重了。
  • 不确定我是否理解这个问题。您可以添加一个新列来存储每一行​​的散列 - 通过触发器或插入/更新填充散列;然后检查使用预先计算的值,不要浪费时间
  • gotqn 因为表很大,而且我们没有与商店的数据库直接连接,我们必须通过文件传递数据......这意味着我需要导出/导入数百万行到一个文件中。我要查找的内容与您的建议类似,但要针对商店/日期执行此操作...因此,每个商店/日期有 1 个哈希值,我可以将其与 HO 的商店/日期进行比较。我试图对几列和计数的总和进行哈希处理,这很有效,但我不确定它是否比使用 Checksum_AGG 和 checksum 函数更好。我很感激你投入的时间。修改说明
  • 使用您的想法,我尝试使用哈希字节创建一个持久计算列,但幸运的是,它失败了,因为该表是在 ANSI_NULLS OFF 的情况下创建的,并且由于此应用程序大规模分布,我无法真正改变这一点......我的双手被束缚,不得不寻找另一个解决方案。在一个完美的世界中,我会在索引中添加计算列,并在每个日期的每个商店聚合它。 +1
猜你喜欢
  • 2011-11-12
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 2011-10-24
相关资源
最近更新 更多