解决方案是使用自然主键吗?我很难想出这些用户的自然主键。问题在于他们都是年轻人,所以他们没有国民保险号码或任何其他我能想到的唯一标识符。我可以创建一个多列主键,但仍有可能发生重复,尽管可能性微乎其微。
有人知道解决方案吗?
谢谢
我认为目前最好保留用户ID的自增功能。
如果未来某时出现了数百万用户的突然激增,那么再考虑修改。 换句话说,解决问题应该在问题出现后再进行,因为“过早地优化是万恶之源”。
回答这个问题-一些自增功能可以允许你种子自增,这样你就可以在不同的节点上获得不同的自增值。 这将避免问题的发生,同时仍然允许使用自增功能。
这里的标准解决方案是使用GUID。但是从索引的角度来看,它们的性能不如其他方法。
如果您需要数百万个ID并且有许多节点,请将主键设置为以下内容的组合:
NodeID int --unique for each node 2 or 4 byte
UserID int --auto increment 8 byte, repeats for each node
这比GUID更好(更小,占用更少的内存,并且更快)。
GUID是不错的选择,但存在碰撞风险(尽管很少发生)。
这可能是一种非标准解决方案,但我想提出:
您可以使用自增数字,但根据将来的分发进行数字空间隔离。
假设您有3个服务器,请按以下方式记录ID:
服务器1:0-9,999,999
服务器2:10,000,000-19,999,999
服务器3:20,000,000-29,999,999
即使在32位整数的限制下,这应该还留有足够的扩展空间(如果您担心也可以使用100,000,000的间隔),并且它基本上保证了系统的唯一性。
除非你想要糟糕的性能和潜在的不良数据,否则永远不要使用自然主键。几乎没有什么自然键是不会随时间而改变的,尤其是名称。如果自然键发生变化,则所有相关的子记录也必须更改。这显然是不好的。
您可以使用 GUID。但是,在数据方面,500万只是微不足道的数字,可能不需要进行更改。我们的系统中有超过1000万个不同的人员,我们只有一个中等大小的数据库,没有分区或需要GUID。
GUID是一种简单的方法,但...
它需要分布到多远?如果只有有限数量的数据库,您可以为每个数据库分配一定范围的数字。例如,第一个数据库自动生成0到999,999范围内的数字,下一个使用1,000,000到1,999,999。这样,它们可以生成用户ID而不会相互干扰。如果数据库包括唯一的标识号码,则可以从该号码自动生成范围。
我认为您不能使用自动递增列来完成此操作,但存储过程可以以这种方式生成数字。
当集群时,GUID作为键是垃圾。如果非集群,则仍需要在另一列上创建聚集索引。
使用整数键,并为每个new
节点/站点
如果您确实有节点/站点,则第二列带有SiteID也可以工作。
我建议您永远不要考虑使用GUID,原因是我目前正在遇到一些问题。假设您有数百万个用户,则可能需要更大的并发度,并且GUID将在插入和删除时破坏您的生活,因为您将在它们上面拥有索引,并且默认情况下它将是一个聚集索引,这意味着每次插入和删除都会物理移动记录。此外,GUID不是连续的,因此每个新插入都有可能出现在页面底部或顶部,因此整体插入和删除操作将变得非常昂贵,如果您删除索引,则选择操作将变得昂贵。
特别是如果您有多个表格并且它们之间存在关系,请勿将GUID视为主键。
以下是我推荐的两种解决方案。
如果您可以创建复合键,那将是完美的,比如说如果它是银行软件,那么branchId、transactionId可能会成为主键,其中branchId是插入记录的节点的标识,而transactionId是分支上的自动编号,这样您就可以获得全程唯一性。
如果以上不是您想要做或考虑的内容,那么您可以使用Guid作为唯一字段,但添加一个自增数字作为主键,这将帮助您降低整体成本,例如当客户端(节点)使用(Web服务)RPC发送数据时,您必须将记录插入服务器数据库,然后将生成一个自动编号,此自动编号可用于未来的选择、删除或更新,但客户端不必知道此自动编号。
我知道第二种解决方案有点令人困惑和复杂,但它仍然比使用Guids作为PK好。但如果适用于解决方案1,请选择它。
当我说成本时,不仅是处理时间,还包括锁定(等待)时间,这完全是浪费金钱,您的四核服务器可能只执行了一半,更多的锁意味着更多的死锁机会,所以我的朋友永远不要使用Guids。
敬礼 Mubashar