我希望有一种相当有效的方法来将整个表压缩为一个哈希值。
我有一些工具可以生成完整的数据表,然后可以使用这些数据表生成更多的表,等等。我试图实现一个简单的构建系统来协调构建运行并避免重复工作。我希望能够记录输入表的散列,以便稍后检查它们是否已更改。构建一个表需要几分钟或几个小时,所以花几秒钟构建哈希是可以接受的。
我使用的一个技巧是将pg_dump的输出通过管道传输到md5sum,但这需要通过网络传输整个表转储,以便在本地机器上进行散列。理想情况下,我希望在数据库服务器上生成哈希。
Finding the hash value of a row in postgresql给了我一种方法来一次计算一行的散列,然后可以以某种方式组合。
任何提示将不胜感激。
- 编辑发布我最终得到的结果:**tinychen的答案对我没有直接作用,因为我显然不能使用'plpgsql'。当我在SQL中实现该函数时,它可以工作,但对于大型表来说效率非常低。因此,我没有将所有行散列连接起来,然后对其进行散列,而是切换到使用“滚动散列”,其中前一个散列与行的文本表示连接起来,然后进行散列以产生下一个散列。这样好多了;显然,在短字符串上额外运行数百万次md5比连接短字符串数百万次更好。
create function zz_concat(text, text) returns text as
'select md5($1 || $2);' language 'sql';
create aggregate zz_hashagg(text) (
sfunc = zz_concat,
stype = text,
initcond = '');
7条答案
按热度按时间hfyxw5xn1#
我知道这是一个老问题,但这是我的解决方案:
wmtdaxz32#
dwbf0jvd3#
就像这样创建一个哈希表聚合函数。
然后你可以使用pg_concat函数来计算表的哈希值。
0lvr5msh4#
我有一个类似的需求,在测试一个专门的表复制解决方案时使用。
@Ben的滚动MD5解决方案(他附加到问题中)似乎很有效,但有几个陷阱让我绊倒了。
第一个问题(在其他一些答案中提到过)是,您需要确保在您正在检查的表上以已知的顺序执行聚合。其语法为eg。
请注意,
order by
位于聚合内部。第二个问题是,对于两个具有相同列内容的表,使用
CAST((example.*)AS text
不会给予相同的结果,除非列是以相同的顺序创建的。在我的例子中,这是不能保证的,所以为了得到一个真正的比较,我必须单独列出列,例如:为了完整起见(以防后续编辑应该删除它),下面是@Ben的问题中zz_hashagg的定义:
f4t66c6m5#
Tomas Greif的solution很不错。但是对于足够大的表 * 无效内存分配请求大小 * 会出现错误。因此,它可以通过两种选择来克服。
**选项1.**无批次
如果表不够大,则使用
string_agg
和bytea
数据类型。**选项2.**带批次
如果上一个选项中的查询以类似
SQL错误[54000]:错误:内存不足详细信息:无法将包含1073741808字节的字符串缓冲区再扩大16个字节。
行计数限制为
1073741808 / 16 = 67108863
,并且表应被划分为多个批。其中,
group by
子句中的3
将行散列划分为16 777 216个批次(2
:65 536,1
:也可以使用其它批处理方法(例如:ntile
)将起作用。P.S.如果你需要比较两个表this post可能会有帮助。
eqfvzcg86#
很棒的答案。
如果有人需要不使用聚合函数,而是维护对几个GiB大小的表的支持,那么在最大表的情况下,您可以使用它,它比最佳答案有 * 小 * 性能损失。
用作:
quhf5bfb7#
至于算法,您可以对所有单个MD5散列进行XOR,或者将它们连接起来并对连接进行散列。
如果您想完全在服务器端完成此操作,则可能必须调用create your own aggregation function。
作为中间步骤,您可以只选择所有行的MD5结果,并通过md5sum运行这些结果,而不是将整个表复制到客户机。
无论哪种方式,您都需要建立一个固定的排序顺序,否则,即使对于相同的数据,最终也可能得到不同的校验和。