[将字符串的MD5用作整数x
的128位表示,如何在Google Bigquery中计算x % y
,其中y
通常相对较小(大约1000)?
Bigquery具有MD5函数,返回具有16个字节(即128位)的BYTES
类型的结果。
(背景:这是为了计算确定性伪随机数。但是,出于传统和兼容性原因,我在算法上没有灵活性!即使我们知道它具有(very slight) bias。]
对于不同的输入字符串和不同的模量,每天需要完成数百万/十亿次,因此希望可以有效地完成。作为回退,我可以使用另一种语言在外部进行计算,然后再上传到Bigquery;但是如果我可以直接在Bigquery中这样做,那就太好了。
我研究了很多数论,所以也许我们可以使用一些数学技巧。但是,我仍然停留在更基本的BiqQuery问题上
BYTES
数组访问字节的子范围吗?具有power of math和冗长的SQL函数:
CREATE TEMP FUNCTION md5_numbers_array(str ANY TYPE) AS ((
SELECT ARRAY_AGG(CAST(CONCAT("0x", TO_HEX(b)) AS INT64))
FROM UNNEST((
SELECT SPLIT(MD5(str), CAST('' AS BYTES))
)) b
));
CREATE TEMP FUNCTION modulo_md5 (str ANY TYPE, m ANY TYPE) AS ((
SELECT MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(0
* 256 + num[OFFSET(0)], m)
* 256 + num[OFFSET(1)], m )
* 256 + num[OFFSET(2)], m )
* 256 + num[OFFSET(3)], m )
* 256 + num[OFFSET(4)], m )
* 256 + num[OFFSET(5)], m )
* 256 + num[OFFSET(6)], m )
* 256 + num[OFFSET(7)], m )
* 256 + num[OFFSET(8)], m )
* 256 + num[OFFSET(9)], m )
* 256 + num[OFFSET(10)], m )
* 256 + num[OFFSET(11)], m )
* 256 + num[OFFSET(12)], m )
* 256 + num[OFFSET(13)], m )
* 256 + num[OFFSET(14)], m )
* 256 + num[OFFSET(15)], m )
FROM (SELECT md5_numbers_array(str) num)
));
SELECT title, modulo_md5(title, 177) result, TO_HEX(MD5(title)) md5
FROM `fh-bigquery.wikipedia_v3.pageviews_2019`
WHERE wiki='en'
LIMIT 100000