我正在使用 Ruby 客户端处理 PostgreSQL,我想使用 SHA-1 哈希 id 对表进行分区,例如
id
------------------------------------------
fe935b318f6976afdec83fa7339ff2069b0bc0c3
d67948e38a645fd5ffdde6dab4dc627b2b19d1b1
0d304f5134b0a46c2248a34c3e9c50ad2b547fdf
进程分区是将数据集划分为 N 个部分,并将每个部分分配给 N 个进程之一。如果您在 RDBMS 中有整数键,这很简单:
select * from items_to_be_processed where MOD(id, N) = ASSIGNED_PARTITION
Ryan Smith建议,如果你有字符串键,你可以在它们上使用 CRC32 来获取整数,然后是模数 - 但是,假设你的键大部分是均匀分布的(就像我认为它会使用 SHA-1 哈希),这会不会更容易?对于N = 4
,例如:
select * from items_to_be_processed where id < ASSIGNED_PARTITION_1
select * from items_to_be_processed where id < ASSIGNED_PARTITION_2 and id >= ASSIGNED_PARTITION_1
select * from items_to_be_processed where id < ASSIGNED_PARTITION_3 and id >= ASSIGNED_PARTITION_2
select * from items_to_be_processed where id >= ASSIGNED_PARTITION_4
所以也许如果N = 2
,那么
select * from items_to_be_processed where id < '8888888888888888888888888888888888888888' <- process 1
select * from items_to_be_processed where id >= '8888888888888888888888888888888888888888' <- process 2
给定 N,我如何计算分区点(8888888888888888888888888888888888888888
分ffffffffffffffffffffffffffffffffffffffff
成两半,可能我什至没有正确计算)?我应该在 SQL (Postgres) 中还是在 Ruby 客户端中进行调用?
PS。灵感来自 MongoDB 食谱中的随机属性思想。
更新
888...
上面的计算不正确 - 这是一种在 Ruby 中执行此操作的方法,感谢 Carl Norum 的回答让我更接近:
>> 'f'*40
=> "ffffffffffffffffffffffffffffffffffffffff"
>> a = 0xffffffffffffffffffffffffffffffffffffffff
=> 1461501637330902918203684832716283019655932542975
>> b = a / 2
=> 730750818665451459101842416358141509827966271487
>> '%x' % b
=> "7fffffffffffffffffffffffffffffffffffffff"
>> '%x' % (b + 1)
=> "8000000000000000000000000000000000000000"