我的主表Users
存储有关用户的信息。我计划将UserId
字段作为表的主键。我完全控制了这些键的创建和分配,我想确保以一种提供良好性能的方式分配键。我该怎么办?
答案 0 :(得分:3)
您有几个选择:
1)最通用的解决方案是使用UUID,如RFC 4122中所述。
例如,您可以拥有一个存储UUID的STRING(36)
。或者您可以将UUID存储为一对INT64
或BYTE(16)
。使用UUID存在一些缺陷,请阅读此answer的详细信息。
2)如果您想节省一点空间并且绝对确定您的用户数量少于几十亿,那么您可以使用INT64然后使用随机数生成器分配UserIds。您希望确定用户少于几十亿的原因是因为Birthday Problem,一旦您拥有4B用户,您获得至少一次冲突的几率大约为50%,并且它们从那里。如果您分配了一个已分配给前一个用户的UserId,那么您的插入事务将失败,因此您需要为此做好准备(通过在生成新的随机数后重试该事务)。
3)如果在“用户”表格中有一些列MyColumn
,您希望将其作为主键(可能是因为您知道您希望使用此列表查找条目经常列),但是您不确定此列会导致热点的趋势(例如,因为它是按顺序生成的还是基于时间戳生成的),那么您还有两个选择:
3a)你可以"加密" MyColumn
并将其用作主键。在数学术语中,您可以对键值使用自同构,这会产生混乱扰乱它们的效果,同时仍然不会多次分配相同的值。在这种情况下,您根本不需要单独存储MyColumn
,而是只存储/使用加密版本,并且可以在应用程序代码中根据需要对其进行解密。请注意,此加密不需要是安全的,而只需要保证原始值的位以可逆方式充分加扰。例如:如果MyColumn的值是按顺序分配的整数,则可以反转MyColumn的位以创建充分加扰的主键。如果您有一个更有趣的用例,可以使用加密算法,如XTEA。
3b)使用复合主键,其中第一部分为ShardId
,计算为hash(MyColumn) % numShards
,第二部分为MyColumn
。哈希函数将确保您不会通过将行分配给单个拆分来创建热点。可以找到有关此方法的更多信息here。请注意,您不需要使用加密哈希,尽管md5或sha512是很好的功能。 SpookyHash也是一个不错的选择。选择正确数量的分片是一个有趣的问题,可能取决于实例中的节点数量;它有效地在热点避免功率(更多分片)和读/扫描效率(更少分片)之间进行权衡。如果你只有3个节点,那么8个分片可能就好了。如果你有100个节点;然后32个分片是一个合理的值。