main table 最简单的主键?
Easiest primary key for main table?
我的主要 table、Users
存储有关用户的信息。我计划有一个 UserId
字段作为 table 的主键。我可以完全控制这些键的创建和分配,并且我想确保以提供良好性能的方式分配键。我该怎么办?
您有几个选择:
- 最通用的解决方案是使用 UUID,如 RFC 4122 中所指定。
例如,您可以有一个存储 UUID 的 STRING(36)
。或者您可以将 UUID 存储为一对 INT64
或 BYTE(16)
。使用 UUID 有一些陷阱,因此请阅读此 answer.
的详细信息
如果您想节省一点 space 并且绝对确定您的用户将少于几十亿,那么您可以使用 INT64,然后使用随机数发生器。你想要确保你拥有的用户少于几十亿的原因是因为 Birthday Problem,一旦你有 4B 用户,你至少发生一次碰撞的几率大约是 50%,而且他们从那里。如果您分配的 UserId 已分配给以前的用户,那么您的插入交易将失败,因此您需要为此做好准备(通过在生成新的随机数后重试交易)。
如果在用户 table 中有一些列 MyColumn
,您希望将其作为主键(可能是因为您知道您需要查找条目经常使用此列),但您不确定此列是否会引起热点(例如,因为它是按顺序生成的或基于时间戳生成的),那么您还有两个选择:
3a) 您可以“加密”MyColumn
并将其用作您的主密钥。在数学术语中,您可以对键值使用自同构,这会产生混乱地打乱它们的效果,同时仍然不会多次分配相同的值。在这种情况下,您根本不需要单独存储 MyColumn
,而您只需要 store/use 加密版本,并可以在必要时在您的应用程序代码中对其进行解密。请注意,这种加密不需要是安全的,而只需要保证原始值的位以可逆的方式充分加扰。例如:如果您的 MyColumn 值是按顺序分配的整数,您可以只反转 MyColumn 的位以创建充分加扰的主键。如果你有更有趣的用例,你可以使用像 XTEA.
这样的加密算法
3b) 有一个复合主键,其中第一部分是 ShardId
,计算为 hash(MyColumn) % numShards
,第二部分是 MyColumn
。散列函数将确保您不会通过将行分配到单个拆分来创建热点。可以找到有关此方法的更多信息 here. Note that you do not need to use a cryptographic hash, although md5 or sha512 are fine functions. SpookyHash 也是一个不错的选择。选择正确数量的分片是一个有趣的问题,可能取决于实例中的节点数量;它实际上是避免热点的能力(更多分片)和 read/scan 效率(更少分片)之间的权衡。如果您只有 3 个节点,那么 8 个分片可能没问题。如果你有 100 个节点;那么 32 个分片是一个合理的尝试值。
我的主要 table、Users
存储有关用户的信息。我计划有一个 UserId
字段作为 table 的主键。我可以完全控制这些键的创建和分配,并且我想确保以提供良好性能的方式分配键。我该怎么办?
您有几个选择:
- 最通用的解决方案是使用 UUID,如 RFC 4122 中所指定。
例如,您可以有一个存储 UUID 的 STRING(36)
。或者您可以将 UUID 存储为一对 INT64
或 BYTE(16)
。使用 UUID 有一些陷阱,因此请阅读此 answer.
如果您想节省一点 space 并且绝对确定您的用户将少于几十亿,那么您可以使用 INT64,然后使用随机数发生器。你想要确保你拥有的用户少于几十亿的原因是因为 Birthday Problem,一旦你有 4B 用户,你至少发生一次碰撞的几率大约是 50%,而且他们从那里。如果您分配的 UserId 已分配给以前的用户,那么您的插入交易将失败,因此您需要为此做好准备(通过在生成新的随机数后重试交易)。
如果在用户 table 中有一些列
MyColumn
,您希望将其作为主键(可能是因为您知道您需要查找条目经常使用此列),但您不确定此列是否会引起热点(例如,因为它是按顺序生成的或基于时间戳生成的),那么您还有两个选择:
3a) 您可以“加密”MyColumn
并将其用作您的主密钥。在数学术语中,您可以对键值使用自同构,这会产生混乱地打乱它们的效果,同时仍然不会多次分配相同的值。在这种情况下,您根本不需要单独存储 MyColumn
,而您只需要 store/use 加密版本,并可以在必要时在您的应用程序代码中对其进行解密。请注意,这种加密不需要是安全的,而只需要保证原始值的位以可逆的方式充分加扰。例如:如果您的 MyColumn 值是按顺序分配的整数,您可以只反转 MyColumn 的位以创建充分加扰的主键。如果你有更有趣的用例,你可以使用像 XTEA.
3b) 有一个复合主键,其中第一部分是 ShardId
,计算为 hash(MyColumn) % numShards
,第二部分是 MyColumn
。散列函数将确保您不会通过将行分配到单个拆分来创建热点。可以找到有关此方法的更多信息 here. Note that you do not need to use a cryptographic hash, although md5 or sha512 are fine functions. SpookyHash 也是一个不错的选择。选择正确数量的分片是一个有趣的问题,可能取决于实例中的节点数量;它实际上是避免热点的能力(更多分片)和 read/scan 效率(更少分片)之间的权衡。如果您只有 3 个节点,那么 8 个分片可能没问题。如果你有 100 个节点;那么 32 个分片是一个合理的尝试值。