Synapse SQL与PySpark中SHA2_256哈希转BIGINT结果不一致的问题及解决方案咨询
Synapse SQL与PySpark中SHA2_256哈希转BIGINT结果不一致的问题及解决方案咨询
我正在尝试将Synapse SQL中生成ETL哈希键的逻辑复刻到PySpark DataFrame中。在SQL里,我用以下语句生成作为唯一行标识的哈希键:
SELECT CAST(HASHBYTES('SHA2_256', CONCAT_WS('|', [col1], [col2], ...)) AS BIGINT) AS EtlHashKey FROM sample_table;
我自己在PySpark里写了一个计算哈希键的函数,代码如下:
import hashlib import struct def compute_hashkey(*values): concat = '|'.join(['' if v is None else str(v) for v in values]) hash_bytes = hashlib.sha256(concat.encode('utf-8')).digest() hashkey = struct.unpack('<q', hash_bytes[:8])[0] # 小端序有符号长整型 return hashkey
我已经验证过,SHA-256的原始十六进制哈希值和SQL中HASHBYTES('SHA2_256', ...)的输出完全匹配(除了SQL会带0x前缀),但把哈希字节转成BIGINT后的结果却和SQL返回的不一致。
示例测试
输入数据:
| col1 | col2 |
|---|---|
| abc | 123 |
SQL输出:EtlHashKey = -7418430994879866706
PySpark输出:EtlHashKey = -5865807261440166157
已排查排除的问题
- 编码不匹配:两端都使用UTF-8编码
- 空值处理:和SQL的
CONCAT_WS逻辑一致,将空值转为空字符串'' - 原始哈希一致性:确认SQL和PySpark生成的SHA-256十六进制哈希完全相同
- 字节序尝试:试过
struct.unpack('>q', ...)(大端序)和struct.unpack('<q', ...)(小端序)两种方式,结果都和SQL不匹配
我的疑问
- SQL Server/Synapse到底是如何将
HASHBYTES的输出转换为BIGINT的? - 为什么原始哈希值完全一致,但转成BIGINT后的结果却不同?
- 要在Python(PySpark)中实现和SQL完全一致的
CAST(HASHBYTES('SHA2_256', ...) AS BIGINT)转换,正确的做法是什么? - 有没有官方文档或者内部实现细节可以说明SQL Server对哈希字节的解析逻辑?
内容来源于stack exchange
相关产品推荐
相关产品推荐

