9

我一直在研究使用 GUID 作为数据库中的主键。目前看来,利大于弊。但是,我发现 GUID 可能不是我想要的。

在我的应用程序中,用户应该能够根据用户友好的 ID 识别对象。因此,例如,如果他们想在不输入全名的情况下获得特定产品,他们可以使用产品的 ID。对于这样的事情,GUID 不容易记住。

我一直在考虑的解决方案是同时使用 GUID 和自动递增整数。GUID 将是行的主键,而自动递增整数将是应用程序过滤函数使用的索引。但是,所有 SQL SELECT、UPDATE、DELETE 语句都将使用 GUID。

我想使用 GUID 的主要原因是防止合并两个数据库时发生冲突。如果 Database #1 和 Database #2 都具有 Product #2,则导入器脚本必须更改 ID 和引用它的所有外键。使用 GUID,我只需要更改表本身中的用户友好 ID,而外键将使用每个导入记录唯一的 GUID,因此无需修改即可工作。

所以,我的问题是:具有自动递增整数索引和 GUID 主键是否存在任何重大问题(除了 GUID 字段的大小和简单的页面碎片)?

4

5 回答 5

14

我总是倾向于在我的数据库中使用代理主键。也就是说:那些主键在问题域中没有实际意义,因此,这些主键永远不会暴露给用户。(如果这个代理主键的类型是 GUID 或身份,我不在乎;这取决于要求)。

如果您说用户应该能够根据用户友好的 ID 识别对象,那么,我认为这个用户友好的 ID 是属于您的“问题域”的值。这意味着,这个 ID 确实应该是您表中的一个属性,但它不应该用作您的表中的主键。

这还允许您轻松修改此类用户友好 ID 的值(如果有必要),而不必担心修改相关的外键。

于 2009-04-03T15:32:59.583 回答
1

“为什么“用户应该能够根据用户友好的 ID 识别对象”?

在我看来,您的用户应该使用代码来识别记录。

假设您的数据库包含产品(正如您在问题中提到的那样)。如果他们有代表产品的代码,用户可以输入,那不是更好吗?

假设您有桌椅,作为用户,我更喜欢使用 tbl 和 chr 而不是 1 和 2 来识别我在说什么。

于 2009-04-03T15:36:51.867 回答
0

MySQL中,您需要将数字设置IDPRIMARY KEYAUTO_INCREMENT可能只有PRIMARY KEY,这意味着它也应该是NOT NULL

您仍然可以UNIQUE INDEXGUID列上定义 a 并在任何地方使用它,尽管InnoDB表将聚集在 numericid上,而不是GUID.

于 2009-04-03T15:33:27.197 回答
0

有一种思想流派说,您永远不应该将您的代理 ID 暴露给外界。所以他们会说,如果你想要一个企业 ID,你应该使用别的东西。

例如,这篇维基百科文章是这样说的:

解离

生成的代理键的值 - 因为它们是生成的且任意的 - 与连续保存的数据的实际含义无关。当检查另一行持有对代理键的外键引用时,仅仅通过查看行本身中的数据是不可能弄清楚它持有该引用的含义的。在尝试理解数据项时必须导航的每个外键连接都会向此间接添加一个层。这也可能使审计更加困难,因为不正确的数据在检查时并不明显。

对于导出和共享的数据,代理键也不自然。一个特别的困难是模式的两个实例可以保存在逻辑上表示相同事物的记录(即,它们在商业意义上是相同的),但由于键的分配历史,它们具有不同的键。处理这个问题的一种方法是采用代理键永远不会导出或导入的规则:它们永远不会暴露在数据库之外,除非作为临时数据(最明显的是,在执行与数据库具有“实时”连接的应用程序时)。

于 2009-04-03T15:35:26.380 回答
0

为了更具体地说明您的问题,是的,在数据​​库中使用 GUID 作为主键还有其他问题:

http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx

问题不在于使用 GUID 作为主键,而是使用非顺序 GUID 作为表的聚集索引

这里的要点是要么使用其他字段作为聚集索引,要么使用顺序 GUID 来避免这种碎片。

于 2009-04-03T15:55:35.693 回答