7

如果我通常有一个包含一百个用户的表,我只会设置一个自动递增的 userID 列作为主键。但是,如果突然我们有 100 万或 500 万用户,那将变得非常困难,因为我希望开始变得更加分布式,在这种情况下,自动增量主键将毫无用处,因为每个节点都将创建相同的主键。

解决方案是使用自然主键吗?我很难为这群用户考虑一个自然的主键。问题是他们都是年轻人,所以他们没有国家保险号码或我能想到的任何其他唯一标识符。我可以创建一个多列主键,但仍然有机会,但重复发生的次数很少。

有谁知道解决方案?

谢谢

4

9 回答 9

11

我会说暂时保持用户 ID 的自动增量。

当你确实有数百万用户突然涌入时,你可以考虑改变它。

换句话说,当你遇到问题时解决它。“过早的优化是万恶之源。”。

要回答这个问题 - 一些自动增量将允许您播种自动增量,因此您可以在不同节点上获得不同的自动增量。这将避免该问题,同时仍允许使用自动增量。

于 2010-04-08T18:17:59.827 回答
8

这里的标准解决方案是使用 GUID。但是,它们在索引方面的表现不会那么好。

于 2010-04-08T18:16:55.067 回答
2

GUID 很好,但容易发生冲突(尽管很少见)。

这可能是一个非标准的解决方案,但我会把它扔在那里:

您可以使用自动递增的数字,但将来根据分布分隔数字空间。

因此,假设您有 3 台服务器。按如下方式记录 ID:

服务器 1:0 - 9,999,999
服务器 2:10,000,000 - 19,999,999
服务器 3:20,000,000 - 29,999,999

即使在 32 位 int 的约束下,也应该留下足够的扩展空间(如果您担心,甚至可以使用 100,000,000 的间隙),并且它基本上保证了整个系统的唯一性。

于 2010-04-08T18:29:47.360 回答
2

如果您需要数百万个 ID 并且有许多节点,则将主键组合为:

NodeID  int   --unique for each node 2 or 4 byte  
UserID  int   --auto increment 8 byte, repeats for each node

这比 GUID 好得多(更小,使用更少的内存,并且会更快)

于 2010-04-08T18:37:49.900 回答
1

除非您想要糟糕的性能和潜在的不良数据,否则切勿使用自然主键。很少有自然键会随着时间而变化,尤其是名称。如果自然键更改,则所有相关子记录也必须更改。这显然很糟糕。

您可以使用 GUIDS。但 500 万在数据方面不算什么,可能不需要改变。我们的系统中有超过 10,000,000 个不同的人,我们只有一个中型数据库,没有分区或需要 GUID。

于 2010-04-08T18:23:33.900 回答
0

GUID 是一种简单的方法,但是...

它需要分布到何种程度?如果是有限数量的数据库,您可以为每个数据库指定一个数字范围以供使用。例如,第一个数据库自动生成 0 到 999,999 范围内的数字,下一个使用 1,000,000 到 1,999,999。这样他们就可以各自生成一个用户 ID,而不会相互碰撞。如果数据库包含一个唯一的数字来识别它,那么可以从这个数字自动生成范围。

我认为您不能使用自动增量列来执行此操作,但存储过程可以以这种方式生成数字。

于 2010-04-08T18:27:12.040 回答
0

集群时,GUID 作为键是垃圾。如果是非聚集的,您仍然需要另一列上的聚集索引。

new对每个节点/站点使用整数键和

  • 以 10 为增量。添加节点时,从 2、3 等开始
  • 使用范围,例如 1-> 1000000、1000000 -> 1999999 等
  • 也不要忘记 -ve。例如,您可以为第二个节点设置 IDENTITY (-1,-1)

如果您确实有节点/站点,那么带有 SiteID 的第二列也将起作用。

于 2010-04-08T18:33:11.073 回答
0

如果您使用 MSSQL,您可以将表的 PK 创建为 UNIQUEIDENTIFIER,并将默认值或绑定设置为 NEWID()。

于 2010-04-08T18:55:52.173 回答
0

我建议您永远不要考虑 GUID,原因之一是目前我遇到了麻烦,假设如果您有数百万用户,那么您可能需要更大程度的并发,并且 Guid 会在插入和删除时毁掉您的生活,因为您将拥有一个索引在它们上,默认情况下它将是一个聚集索引,这意味着当你有一个聚集索引时,每次插入和删除都会物理移动记录,而且 Guid 不是连续的,所以每个新插入都出现在底部的可能性为零或页面顶部。因此整个插入和删除操作将变得非常昂贵,如果您删除索引,那么您的选择将变得昂贵。

特别是如果您有多个表并且它们之间存在关系,则不要将 Guids 视为主键。

我推荐以下两种解决方案。

  1. 如果您可以制作完美的复合键,例如银行软件,那么它可能是 branchId,transactionId 将成为主键,其中 branchId 是插入记录的节点的身份,transactionId 是分支的自动编号,因此您将获得唯一性一路走来。

  2. 如果上面不是您喜欢做或考虑的,那么您可以将 Guid 用作唯一字段,但添加一个自动增量编号作为主键,这将帮助您降低总体成本,例如客户端(节点)使用(web服务)RPC,然后你必须将记录插入服务器数据库,然后将生成一个自动编号,此自动编号可用于将来的选择、删除或更新,但客户端不必知道此自动编号

我知道第二种解决方案有点混乱和复杂,但它仍然比使用 Guids 作为 PK 更好。但如果解决方案 1 适用,那就去吧。

当我说成本时,它不仅是处理时间,还有它的锁定(等待)时间,这完全是浪费金钱,你的四核服务器可能正在执行一半,更多的锁意味着更多的死锁机会,所以我的朋友永远不会使用指南。

问候穆巴沙尔

于 2010-04-08T19:47:55.337 回答