您如何看待您的主键?[关闭]


88

在我的团队中进行的相当活跃的讨论中,我被认为是大多数人喜欢的主键。我们有以下几组:

  1. Int / BigInt哪个自动增量是足够好的主键。
  2. 主键应至少包含3列。
  3. id,GUID和人类可读的行标识符都应区别对待。

PK的最佳方法是什么?如果您能证明自己的观点,那就太棒了。上面有没有更好的方法?

编辑:任何人都有一个简单的示例/算法来生成很好地缩放行的人类可读的标识符?


1
由于这是主观的,因此它应该是社区Wiki
John Sheehan

2
“应该至少由3列组成主键”?这是什么意思?您能否提供进一步的定义?还是这是#3的一部分?
S.Lott

@ PK(NEWID(),NEWID(),NEWID())

@pst:为什么要这样做?为什么PK中必须有三列?为什么是一四个?
S.Lott 2010年

我可以看到三列PK,如下所示:LocalID(自动递增int),GlobalID(GUID),ForeignId(诸如RolesType之类的外键)等。LocalID+ ForiegnId可以是复合键组合。该Guid用于其他网站/服务。就我个人而言,我不会这样做,我只会使用Guid + ForiegnId。
耶拉德(Jerad)

Answers:


76

如果要在数据库与偶尔连接的应用程序之间进行任何同步,则应使用GUID作为主键。调试有点痛苦,因此除了这种情况外,我倾向于坚持自动递增的整数。

Autoincrement int应该是默认值,使用它们应该是合理的。


3
不需要GUID,只需将步长更改为10或20,或者将来可能需要与许多服务器同步即可。
罗伯特·巴思

43
至少90%的时间不需要GUID,这会浪费空间。
乔纳森·莱夫勒

8
我真的觉得GUID太过分了。从来没有需要GUID作为我的主键。
西里尔·古普塔

7
或者,不要浪费空间并冒着与GUID冲突的风险,而应使用原始主键和一个小的标识符的组合密钥,其中每个同步源的小标识符都不同。
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 2010年

5
我工作过的一家商店使用了GUID,即使有可用的公共标识符(例如ISO国家或语言代码),也都使用了GUID。甚至当布尔或CHAR(1)足够时,例如sex。不用说,这是一场噩梦。
卢米

56

我没有看到一个答案可以指出(我认为)真正的基本要点-即,主键保证了您不会在表中获得同一真实世界实体的两个条目(例如在数据库中建模)。此观察有助于确定主键的优点和缺点。

例如,在(美国)状态名称和代码表中,名称或代码可以是主键-它们构成两个不同的候选键,并且选择其中一个(通常是较短的-代码)作为主键。首要的关键。在功能相关性(以及连接相关性-1NF到5NF)的理论中,关键的是候选键而不是主键。

举个反例,人名通常是主键的错误选择。有很多人以“约翰·史密斯”(John Smith)的名字或其他类似的名字来称呼。即使考虑到中间名(请记住:并非每个人都有一个中间名,例如,我没有),但仍有很多重复的余地。因此,人们不会将名称用作主键。他们发明了诸如社会安全号(SSN)或员工号之类的人工密钥,并使用它们来指定个人。

理想的主键应简短,独特,令人难忘且自然。在这些特征中,唯一性是强制性的;鉴于现实世界数据的限制,其他人必须灵活应对。

因此,在确定给定表的主键时,您必须查看该表代表什么。表中哪些列值集或哪些集唯一地标识表中的每一行?这些是候选键。现在,如果每个候选键由4或5列组成,那么您可能会认为这些键太笨拙而不能做成一个好的主键(主要是出于简短的考虑)。在这种情况下,您可能会引入一个替代密钥-一个人工生成的数字。通常(但不总是),一个简单的32位整数足以代替代理密钥。然后,您可以将此代理键指定为主键。

但是,您仍然必须确保将其他候选键(因为替代键也是候选键,以及所选的主键)都保持为唯一标识符-通常通过在这些列集上设置唯一约束来实现。

有时候,人们发现很难识别什么使行变得独特,但是应该做些什么,因为仅仅重复一条信息并不能使它变得更真实。而且,如果您不小心并且确实得到两(或更多)行声称要存储相同的信息,然后又需要更新该信息,则有一种危险(尤其是如果您使用游标),您只会更新一行而不是每一行,因此这些行是不同步的,没有人知道哪一行包含正确的信息。

在某些方面,这是一个很强硬的观点。

我在需要时使用GUID并没有特别的问题,但是它们往往很大(如16-64字节),并且使用频率很高。通常,一个很好的4字节值就足够了。由于每个索引页的值较少,因此使用4字节值足以满足需要的GUID浪费磁盘空间,并且甚至减慢了索引访问数据的速度,因此索引将更深,必须读取更多页才能到达索引页。信息。


10
关于带有美国州名的样本,我宁愿使用单独的代理键,这仅仅是因为代码是您无法控制的。如果由于某种原因它们应该改变,那么您会遇到问题。
Dirk Vollmar,2009年

(续)例如,在重新统一后的1990年代,德国用5位数字系统替换了4位邮政编码系统。
德克·沃尔玛2009年

@divo:我坚决主张使用人工/代用密钥,但是即使我认为4位数到5位数的邮政编码也不是一个很好的例子。邮政编码通常不用作任何东西的钥匙。(什么时候是您最后一次查询PostalCode表以查找有关该代码的信息?不,它几乎专门用作地址的一部分,而没有在其他任何表中引用。我想说的是,您的建议与使用代理自己的地址密钥。)
ErikE,2010年

@Emtucifor:是的,也许ZIP不是一个很实际的例子,但是我的意思是,如果您的代理密钥的一部分不受控制并且出于任何原因进行更改,则您会遇到麻烦。想像一下有人创建了新的社会保险号码方案,新的ISSN方案,或者-也许更现实的公司决定合并后创建新的产品ID系统,为员工分配新的员工编号以调整其成长等。所有这些都是虚构的示例,但是,正如我之前关于ZIP的示例所示,有时一个完善的系统可能会发生变化。
德克·沃尔玛

2
您的第一点是正确的。此约束有一个名称。称为“实体完整性”。EI要求每个实体都有唯一的身份。主键通常满足此要求,除非使用自动编号。使用自动编号,除自动编号外,您可以获得两行相同的行。这通常会破坏实体的完整性。
Walter Mitty

26

这只是一个宗教问题,因为人们寻求普遍的正确答案。您的团队和该SO线程都显示出很大的分歧这一事实应该表明,有充分的理由在不同情况下使用您描述的所有解决方案。

  • 如果表中没有其他属性或一组属性适合于唯一地标识行,则代理键很有用。
  • 在可能的情况下,最好使用自然键以使表更易于阅读。自然键还允许从属表中的外键包含实际值而不是代理ID。例如,当您需要存储state(CA,TX,NY)时,您不妨使用char(2)自然键而不是int。
  • 在适当的地方使用复合主键。id当存在完美的复合键时,不要不必要地添加“ ”替代键(在多对多表中尤其如此)。在每个表中对三列键的授权都是绝对的废话。
  • 当您需要在多个站点上保留唯一性时,GUID是一种解决方案。如果您需要主键中的值唯一但又不是有序或连续的,则它们也很方便。
  • INT vs. BIGINT:表需要主键的64位范围并不常见,但是随着64位硬件可用性的增加,它不应该成为负担,并且可以确保您不会溢出。INT当然较小,因此,如果空间有限,则可以带来一点优势。

6
我完全不同意一个人的能力。自然键太可怕了。如果要更改数据怎么办?哦,你不能。在复合自然键上编写联接很痛苦。将该复合键携带到所有相关表中是一种浪费。
罗伯特·巴思

2
@Robert:阅读有关“ ON UPDATE CASCADE”的信息。但是,我理解了您的意思,并且我同意大多数时候最好使用代理键,因为属性可能会发生更改并且是不唯一的。
比尔·卡温

1
主键应该是不变的。在这种情况下,级联更新只是一个糟糕的设计决策的丑陋hack。自然键从来都不是首选。与复合键一样,它们像瘟疫一样蔓延开来。任何拥有3个月以上数据库开发经验的人都会知道这一点。
FDCastel

7
@FD:我不同意您的明确表述,并且自1992年以来我就一直在开发SQL数据库。但是,可以肯定的是,代理键最能保持不变。
比尔·卡温

20

我喜欢The Database Programmer博客作为此类信息的来源。

3个主键列?我要说的是,列应该根据业务规则的要求具有适当的唯一约束,但是我仍然需要单独的代理键。复合密钥意味着业务逻辑将输入密钥。如果逻辑发生变化,那么整个架构就被搞砸了。


2
他们改变他们的链接,这里是更新书签:database-programmer.blogspot.com/2008/09/...
布莱恩Rehbein

刚刚继承了这样的项目。他们想做的第一件事就是炸毁该架构。代理键FTW。数据库FTL中的业务逻辑。
杰森


11

有点题外话,但是我不得不强迫...

如果您的主键是GUID,请不要使其成为聚集索引。由于GUID是非顺序的,因此几乎在每次插入过程中,数据都会在磁盘上重新排列。(糟糕)如果将GUID用作主键,则它们应该是非聚集索引。


1
非常好的一点-需要区分主键的LOGICAL概念(对于使用GUID可能是有效的,尤其是在涉及复制的情况下),以及集群键的PHYSICAL概念- 绝不应该是GUID,因为这会导致过度的索引碎片化
marc_s

3
这实际上是不准确的。数据将按顺序插入,这取决于GUID的随机性,最终可能会出现在表中的任何位置。在没有空间的情况下,将发生页面拆分,但是肯定不会“甚至在每次插入期间在磁盘上重新排列”也不会关闭。
拉尔夫·希灵顿2009年

@Ralph,您是对的,不是每次插入,但足以使性能下降20倍。sql-server-performance.com/articles/per/…–
波特曼

SQL Server函数newsequentialid()解决了GUID的索引碎片问题(尽管如果您绝对不需要全局唯一性,则24字节仍然有点多余)。请参阅msdn.microsoft.com/en-us/library/ms189786.aspx。
ErikE 2010年

10

我总是使用代理键。替代密钥(通常是标识列,自动增量或GUID)是其中密钥本身不存在于数据本身中的一种。另一方面,自然键本身就是唯一标识行的键。据我所知,几乎没有真正的自然钥匙。甚至在美国,诸如SSN之类的东西都不是自然键。复合主键是一场灾难,等待发生。您无法编辑任何数据(这是使用或不使用复合键的任何自然键的主要缺点),但更糟糕的是,使用复合键后,您现在必须将该键数据保留到每个相关表中。真是浪费。

现在,为了选择代理键,我坚持使用身份列(我主要在MS SQL Server中工作)。GUID太大,Microsoft建议不要将它们用作PK。如果您有多台服务器,您要做的就是使增量为10或20,或者您认为同步/扩展到的最大服务器数量,然后为每个后续服务器上的每个表增加种子,您将永远不会发生数据冲突。

当然,由于增加的缘故,我将标识列设为BigInt(否则称为long [64位])。

进行一点数学运算,即使您将增量设为100,表中仍然可以有92,233,720,368,547,758(> 92个万亿)行。


9

我认为在“ Primary”键短语中使用“ Primary”一词确实是一种误导。

首先,使用“键”是表中唯一的一个属性或一组属性的定义,

然后,拥有任何键都可达到几个经常相互矛盾的目的。

  1. 用作与该父表有关系的子表中一个或多个记录的联接条件。(在这些子表中显式或隐式定义外键)
  2. (相关)确保子记录在父选项卡中必须具有父记录; e(子表FK必须作为父表中的键存在)
  3. 为了提高需要快速在表中查找特定记录/行的查询的性能。

  4. 通过防止将代表同一逻辑实体的重复行插入表中来确保数据一致性。(这通常被称为“自然”键,并且应由相对不变的表(实体)属性组成。)

显然,任何无意义的完整非自然键(如GUID或自动生成的整数)都完全无法满足#4。

但是通常,对于许多(大多数)表,可以提供#4的完全自然的键通常会包含多个属性,并且过宽或过宽,以至于将其用于#1,#2或#3用途将导致无法接受性能后果。

答案很简单。同时使用。对其他子表中的所有联接和FK使用简单的自动生成积分键,但要确保每个需要数据一致性的表(很少有表不需要)具有备用的自然唯一键,以防止插入不一致的数据行。 ..另外,如果您始终拥有两者,那么所有反对使用自然键(如果改变的话,我都必须更改它被称为FK的每个位置)的反对意见就变得毫无意义,因为您没有为此使用它。 ..您只在一个表中使用它,因为它是PK,以避免不一致的重复数据...

对于GUID,请务必小心使用它们,因为在索引中使用guid会使索引碎片破裂。用于创建它们的最常见算法将GUID的“随机”部分放在最高有效位中。这增加了添加新行时对常规索引进行碎片整理/重新索引的要求。


SQL Server函数newsequentialid()解决了GUID的索引碎片问题(尽管如果您并非绝对需要全局唯一性,则24字节仍然有点多余)。请参阅msdn.microsoft.com/en-us/library/ms189786.aspx。
ErikE

糟糕,我的意思是说16个字节。
ErikE'2

8

您不应该做的一件事就是使用智能钥匙。这是一个密钥,其中有关记录的信息被编码在密钥本身中,并且最终会咬住您。

我在一个地方工作,那里的主键是帐户ID,它是字母和数字的组合。我不记得任何细节,但是,例如,那些类型一定的帐户将在600范围内,而另一个类型的帐户则以400开始。那太好了,直到该客户决定要求两个工作类型。或更改了他们所做的工作类型。

另一个地方,使用树中的位置作为记录的主键。因此会有类似以下的记录。

Cat1.subcatA.record1
Cat1.subcatA.record2
Cat1.subcatB.record1
Cat2.subcatA.record1

当然,客户想要的第一件事是在树上移动物品的方法。整套软件在此之前就已失效。

拜托,拜托,拜托,如果您要编写我必须维护的代码,请不要使用智能钥匙!


我完全同意。Smartkeys =哑键。
罗伯特·巴思

2
但这并不意味着自然键是愚蠢的。但是好点。

4

我喜欢自动增量作为主键。我内心深处知道这是一个解决方案,但是它确实使按数据添加时(ORDER BY ID DESC,再例如)进行排序变得如此容易。

3列听起来很难让人解析。

这就是权衡取舍-您需要多少关系功能,而不是让此处的表对于人类的询问是可以理解的(相对于存储过程或编程接口)。

自动增量对我们人类而言。:-(


4

通常,这取决于。

就个人而言,我喜欢自动增量整数。

但是,我可以告诉您的一件事是,永远不要信任来自其他来源的数据作为密钥。我发誓,每次我做完这些,都会让我伤心。好吧,再也不会!


3

应该至少有3列组成主键。

我不明白

您是否在谈论“自然钥匙”,例如“姓名和出生日期”?如果存在,那么自然键可能是理想的选择,但是大多数自然键候选者不是唯一的(几个具有相同名称的人),或者不是恒定的(有人可以更改其名称)。

Int / BigInt哪个自动增量是足够好的主键。

我更喜欢Guid。自动增量的潜在问题是该值(例如“订单ID”)是由数据库实例(例如“销售数据库”)分配的……如果以下情况不能完全起作用(相反,您开始需要复合键)您曾经需要合并由多个数据库实例创建的数据(例如,来自多个销售办事处,每个都有自己的数据库)。


主键必须是唯一的,但不需要是恒定的。因此,用“ ON UPDATE CASCADE”声明外键。但是假设主键是恒定的有助于简化许多应用程序。这是代理密钥的好处之一。
Bill Karwin

3

RE GUID的

当心,如果这将是一个真的真的真的真的很大的数据库,大量的负载,并实现快速访问。

在我的上一份工作中,我们拥有100到5亿条记录的数据库,我们的数据库专家强烈反对GUID,并要求使用适当大小的十进制数字。他们认为(在Oracle中)字符串Guid(与十进制值)在内部存储中的大小差异将在查找中产生非常明显的差异。(更大的键=遍历更深的树)

GUID的随机性还显着降低了索引页的填充因子-这大大增加了撕裂和磁盘I / O。


“减少填充因子”?不确定这意味着“填充因子”是一次交易,定义为在建立索引时在索引的叶级上请求的可用空间的百分比。GUID值通过其在插入因子提供的自由空间中的插入上的叶级宽度上的随机性质分布而分布。
拉尔夫·希灵顿

1
由于GUID何时是字符串?任何适当的DBMS都应将GUID内部存储为16字节。以十六进制表示形式存储为32个字节是不合理的!(或带有破折号的36,或带有花括号的38)
ErikE 2010年

2

自动递增列。我能够使我的代码与SQL Server或Oracle无缝协作,一个使用身份,另一个使用通过我的DAL的序列,我再也不会高兴了。我同意,如果您正在执行复制或发送数据以在以后处理时接收它,则有时需要GUID。


2

我一直使用代理密钥-一个称为'id'的自动递增整数。我可以看到很多理由来执行此操作,即使另一个选择很明显:

  • 一致性
  • 数据独立(唯一,不会因格式更改而破坏)
  • 人类可读

...并且没有明智的理由不这样做:

  • 连接中的歧义?-别名表是更好的做法,恕我直言
  • 最佳表?-删除每个条目一个字节是过早的优化,恕我直言
  • 每桌决定?-不再一致
  • 缩放问题?-嗯?为什么?
  • 分层数据结构?-这是非正规化,是宗教的另一主题。可以说我在理论上在某些情况下是粉丝,但在实践中从不:)

我从未想到或遇到过的明智原因总是受到欢迎...


1

这是经典的“取决于”。每个项目都没有一个正确的答案。我喜欢不同情况下的不同事物。这取决于我是否使用ORM及其支持的内容。它取决于整体体系结构(是否分布)。只需选择一个您认为可行的选项,然后继续讨论制表符和空格。


他仍然希望知道如何使用它。只有有了这些意识,才能相信自己的自我选择……
Nicholas Leonard

1

我倾向于使用选项#1或#3,具体取决于大小,连接的人数以及是否为多数据库服务器。

选项#2对我来说没有多大意义。如果三个记录中的任何一个都不足以标识唯一记录,则有可能(无需进行额外的伪造)两个记录的两个记录在所有三列中都具有相同的值。如果要对这三种方式的任何组合实施唯一性,则只需为其添加索引。


1

我只使用自动增量int或GUID。我有99%的时间使用了auto-increment int。这就是我第一次学习数据库时就被教导要使用的,并且从未遇到过不使用它们的原因(尽管我知道GUID会更好的原因)。

我喜欢自动增量整数,因为它有助于提高可读性。例如,我可以说“看一下记录129383”,某人进入并找到它很容易。使用GUID几乎是不可能做到的。


2
为什么这么说 似乎许多人使用自动递增整数。如果它能够很好地满足您的需求,那就不是那么糟糕。
dtc

1

通过基本的定义性答案后,构成良好主键的大部分内容留给了宗教和休息室讨论。如果您具有并将始终唯一地映射到单个行的内容,则它将作为主键可以很好地工作。在那之后,还有其他注意事项:

  • 主键定义是否过于复杂?是否为了遵循“最佳实践”而避免引入不必要的复杂性?
  • 是否有更好的主键可能需要较少的数据库开销(例如INTEGER与VARCHAR等)?
  • 我绝对确定我的主键的唯一性和定义不变性不会改变吗?

这最后一个可能是吸引大多数人使用诸如GUID或自增整数列之类的东西的原因,因为依靠地址,电话号码,名字/姓氏等之类的东西,只是不要砍掉它。我能想到的关于人的唯一不变性就是SSN,但是我什至不能100%地确定那些永远唯一的人。

希望这有助于增加一些清晰度...


在某些历史案例中,SSN不是唯一的。
Bill Karwin

1

我使用主键(我认为是最好的)的方法是避免使用“默认”方法。这意味着我不只是拍打一个自动递增的整数然后称它为“一天”,我还看着问题说:“是否存在一列或一组列将始终是不固定的并且不会改变?” 如果答案是肯定的,那么我会采用这种方法。


这是否意味着您“尽可能避免自动递增整数”?我的理解是,行业专家认为大型数据库上的最佳性能来自最小签名,索引的增量单列PK。
Hardryv '02

1
我一直认为专家会使用最好的工具来完成工作
Andrew G. Johnson

1

几乎总是整数。

除了更小/更快地处理之外,它们还有其他很好的理由。您想记下哪个-“ 404040”或“ 3463b5a2-a02b-4fd4-aa0f-1d3c0450026c”?


后者可以是一个整数,在其基数16中添加了破折号。但是,是的,404040的处理速度比长GUID更快。再一次,0甚至更快地处理,因为它不需要一点数据!
斯特拉格

1

只是有点相关,但是最近我在有小的分类表(基本上是表示代码中的ENUM的分类表)时开始做的一件事是,我将主键设为char(3)或char(4)。然后,使那些主键代表查找值。

例如,我有一个内部销售代理的报价系统。我们为“报价类别”分配了每个报价行项目之一。因此,我有一个名为“ tCostCategories”的类型查找表,其中主键为“ MTL”,“ SVC”,“ TRV”,“ TAX”, “ ODC”。查找表中的其他列存储更多详细信息,例如代码的常规英语含义,“材料”,“服务”,“旅行”,“税”,“其他直接成本”,等等。

这真的很不错,因为它不使用比int更多的空间,并且在查看源数据时,不必链接查找表即可知道该值到底是多少。例如,引用行可能看起来像:

1部件号$ 40 MTL
2其他部件号$ 29.99 SVC
3部件号2 $ 150 TRV

使用int表示类别,然后在所有行上链接1,2,3,要容易得多-您将数据摆在面前,而且性能似乎根本没有受到影响(不是因为我进行了真正的测试。)

就真正的问题而言...我喜欢RowGUID uniqueidentifiers。我不是100%对此,但不是所有行都具有内部RowGuid吗??如果是这样,那么使用RowGuid实际上会比ints(或其他任何事情)占用更少的空间。我所知道的是,如果M $在GreatPlains中使用就足够了,那么对我来说就足够了。(我应该躲起来吗?)


1

哦,我使用GUID的另一个原因-我使用了分层数据结构。也就是说,我有一个表“ Company”和一个表“ Vendor”,主键与其匹配。但是我还有一个“制造商”表,该表也来自“公司”。供应商和制造商通用的字段不会显示在这些表中,而是显示在公司中。在此设置中,使用int比Guids痛苦得多。至少,您不能使用身份主键。


1
是的,您可以,只是不使子类型表具有identity属性,而是使它们获得超类型表值的显式插入。请参阅stackoverflow.com/questions/2112882/…–
ErikE,2010年

1

只要我信任自然键,我就会喜欢它们。我愿意付出较小的性能价格,以便使用对主题专家有意义的键。

对于描述实体的表,应该有一个简单的自然键,用于以与主题对象相同的方式标识各个实例。如果主题没有实体之一的可信赖标识符,那么我将使用代理密钥。

对于描述关系的表,我使用了复合键,其中每个组件都引用了参与该关系的实体,因此引用了实体表中的一行。同样,使用复合键的性能影响通常很小。

正如其他人指出的那样,术语“主键”有点误导。在关系数据模型中,使用的术语是“候选键”。单个表可能有多个候选键。从逻辑上讲,每个人都和另一个人一样好。选择其中一个作为“主要”并通过该键进行所有引用只是设计者可以做出的选择。


请描述一些示例可信赖的自然键?
ErikE 2010年

1
“可信赖”本身不是密钥的属性。相反,它与提供数据的人员的上下文中的密钥有关。如果您要编写要出售给实际将要管理数据的人的应用程序,则必须猜测哪些密钥对客户是可信赖的。鉴于客户的多样性,几乎可以肯定的是,对于部分客户来说,您肯定会猜错。
沃尔特·米蒂

上面已经说了,这是我们信任的密钥示例。我们有一个关于课程的数据库。它包括有关课程,预定课程产品,有资格教授课程的导师,课程前提条件,学费等方面的教科书和其他课程材料。当课程开发创建新课程时,他们要做的第一件事就是分配课程代码。他们负责确保课程代码是唯一的,并且一旦分配,课程就永远不会更改其代码。这是提供给我们的数据的一部分。
Walter Mitty

受信任的自然密钥的另一个很好的例子是VIN(车辆识别号)。在过去的多年中,每辆新车都附有VIN。可以相信它们是唯一且不变的。
Walter Mitty

1

指导期。

如果您需要扩展或需要通过其他方式分配主键,则它们将成为您的朋友。您可以为其他所有内容添加索引。


更新以澄清我的陈述。

我曾在许多不同类型的网站上工作。从小型单台服务器交易到具有多个数据库和Web服务器的大型交易。当然,有些应用程序可以将int作为主键自动递增。但是,这些都不适合我做事的模式。

使用GUID时,您可以在任何位置生成ID。它可以由远程服务器,您的Web应用程序,数据库本身甚至在多主机情况下的多个数据库中生成。

另一方面,只能在主数据库中安全地生成自动递增的INT。同样,如果您的应用程序与该备份数据库服务器紧密相关,而您不必担心横向扩展,那么这可能没关系。

当然,使用GUID意味着您必须每晚进行重新索引编制过程。但是,如果您使用的不是自动递增的INT,则无论如何都应该这样做。哎呀,即使以INT为主要对象,您也可能需要重新生成其他索引来处理碎片。因此,使用GUID不会完全增加另一个问题,因为无论如何都需要执行这些任务。

如果您查看其中的大型应用程序,您会发现一些重要的事情:它们都使用Base64编码的GUID作为键。原因很简单,GUID的使用使您可以扩展轻松地而尝试横向扩展INT时可能会遇到很多麻烦。

我们最新的应用程序经历了一段时间的沉重插入,持续了大约一个月。之后,90%以上的查询全部选择用于报告。为了增加容量,我可以在这个大插入期间启动其他数据库服务器。然后将它们轻松合并到一个数据库中进行报告。尝试使用INT来做到这一点绝对是一场噩梦。

坦率地说,每当您对数据库进行集群或设置复制时,DB服务器将始终要求您在表上具有GUID。因此,如果您认为您的系统可能需要扩展,请选择一个好的系统。


您是否曾经检查过索引的填充因子?GUID的'em'em瑞士奶酪的随机性-大大降低了其有效性。
stephbu

2
“ Guids.period”:太错了。应在适当的地方使用GUID。正如另一位评论者所指出的那样,这可能会使程序员的生活变得轻松,但会影响数据库的整体大小和性能。
米奇·

最终,我可以在多个数据库服务器上扩展我的应用程序而不会出现问题。但是我想你们在小型网站上工作。
2009年

3
GUID 可能是逻辑主键确定,但永远不使用GUID列作为聚集键-你会被淹没在索引碎片导致性能不佳.....
marc_s

我当然不会宣布“ Guids.period”。关于这个主题的信息-实际上,即使是在一个充斥着“最佳实践”的行业中,这种陈述在默认情况下也会使您处于摇摇欲坠的状态(尤其是那种陈述)。任何像GUID一样痛苦的处理都需要一些严格的理由,正如JL所说,我认为我们大多数人都将其视为万不得已。就像您在发布时未阅读其余线程一样。
Hardryv '02

0

无论您是否意识到,这都是一个复杂的主题。可能属于此StackOverflow常见问题解答的部分。

我在这里不应该问什么问题?

避免提出主观,争论或需要扩展讨论的问题。这是一个可以回答问题的地方!

这已经辩论了多年,并将继续辩论多年。我所看到的唯一共识是,答案是可以预测的,具体取决于您是否问OO对象(GUID是唯一的方法!),数据建模者(自然键是唯一的方法!),或面向性能的DBA(INT是唯一的方法!)。


我不会让讨论持续太久。我只是很好奇看到普遍共识。
Perpetualcoder

1
我说问你想问的任何问题!否则,这个社区将变得像维基百科一样变得静止和过度控制。在我看来,有些时候您需要让人们问选择问的问题。相信他们,他们可能会相信自己!
尼古拉斯·伦纳德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.