12

我们使用 Guid 作为数据库中实体的主键。传统上,我们遵循让数据库在插入期间为实体设置 ID 的模式,我认为主要是因为这通常是您使用自动增量字段或其他方式处理事情的方式。

我越来越发现在对象构造期间在代码中进行键分配要方便得多,主要原因有两个:

  1. 您知道,一旦对象的构造函数运行,它的所有字段都已初始化。您永远不会有“半生不熟”的物体在四处乱窜。
  2. 如果您需要执行一批操作,其中一些操作取决于知道对象的键,您可以一次完成所有操作,而无需往返数据库。

有什么令人信服的理由这样做吗?也就是说,当使用 Guid 作为键时,是否有充分的理由将键分配留给数据库?

编辑: 很多人对是否应该将Guids用于PK(我知道)有强烈的意见,但这并不是我问题的重点。

除了集群问题(如果您正确设置索引,这似乎不是问题),我还没有看到避免在应用程序层创建键的令人信服的理由。

4

9 回答 9

5

我认为通过在客户端创建它们你做得很好。正如您所提到的,如果您让数据库这样做,您必须找到某种方法(真的想不出任何方法)来获取该密钥。如果您使用的是身份,则可以使用调用来获取为表创建的最新身份,但我不确定是否存在这样的 guid。

于 2009-01-30T18:44:44.087 回答
4

通过在 C# 中执行此操作,您可能会冒重新分配 GUID 并将其保存回数据库的风险。通过让数据库负责它,您可以保证此 PK 不会更改,也就是说,如果您设置了适当的约束。话虽如此,您可以在 C# 代码中设置类似的约束,以防止在分配唯一 id 后更改它,但是您必须在所有应用程序中执行相同的操作......在我看来,在 C# 中使用它听起来比数据库更需要维护,因为数据库已经内置了防止更改主键的方法。

于 2009-01-30T18:44:53.087 回答
2

有趣的问题。

传统上,我也使用数据库分配的 guid,但最近我正在开发一个 Windows Mobile 应用程序,而 SQL CE 数据库不允许使用 newguid,所以我不得不在代码中进行。

我使用 SQL 复制将数据从移动设备获取到服务器。在过去的 6 个月中,我有 40 个 SQL CE 客户端将超过 100000 条记录同步回 SQL 2005 服务器,没有一个丢失或重复的 guid。

所需的额外编码可以忽略不计,在插入之前了解 guid 的好处实际上减少了一些复杂性。

我没有进行任何性能检查,因此除了性能之外,我看不出有任何理由不按照您的建议实施 guid 处理。

于 2009-01-30T21:07:26.343 回答
1

GUID 对性能来说很糟糕

我会把它留在数据库中,特别是现在 SQL Server 有NEWSEQUENTIALID()不再导致插入页面拆分,因为值是随机的,创建的每个 NEWSEQUENTIALID 都将大于前一个......唯一的问题是它只能用作默认值

于 2009-01-30T18:45:16.317 回答
1

如果您必须在 GUI 之外进行插入(考虑从其他供应商导入数据或从您购买的公司导入数据并且必须与您的数据合并),则不会自动分配 GUID。这不是一个无法克服的问题,但仍然需要考虑。

于 2009-01-30T21:05:46.360 回答
0

我让一个空的 Guid 指示该对象虽然已构建,但尚未插入(或从)数据库中检索。

于 2009-01-30T18:46:44.347 回答
0

正如 SQLMenace 所指出的,标准 GUID 会对索引和分页产生负面影响。在 C# 中,您可以使用一点 P/Invoke 的乐趣来生成像 NEWSEQUENTIALID() 这样的顺序 GUID。

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

这样,您至少可以继续使用 GUID,但在生成它们的方式和位置方面获得更大的灵活性。

于 2009-01-30T21:23:29.307 回答
0

好的,是时候插话了。我会说生成的 GUID 客户端保存到数据库是最好的方法——前提是你碰巧使用 GUID 作为你的 PK,我只在一种情况下推荐:断开连接环境。

当您使用断开连接的模型进行数据传播(即 PDA/手机应用程序、用于有限连接场景的笔​​记本电脑应用程序等)时,作为 PK 生成客户端的 GUID 是最好的方法。

对于其他所有情况,使用自动增量身份 PK 可能会更好。

为什么?嗯,有几个原因。首先,通过使用跨行聚集 PK 索引,您确实获得了很大的性能提升。GUID PK 和聚集索引不能很好地配合使用——即使使用 NEWSEQUENTIALID,顺便说一下,我认为它完全忽略了 GUID 的意义。其次,除非您的情况迫使您不要这样做(即您必须使用断开连接的模型),否则您确实希望保持一切事务性并同时插入尽可能多的相互关联的数据。

于 2009-01-30T21:52:18.747 回答
0

除了集群问题(如果您正确设置索引,这似乎不是问题),

作为索引的 GUID 总是非常混乱 - 没有“适当的”设置可以避免这种情况(除非您在 SQL Server 引擎中使用 NEWSEQUENTIALGUID 函数)。

恕我直言,最大的缺点是大小 - GUID 是 16 字节,INT 是 4。PK 不仅存储在主键树中,而且还存储在每个非聚集索引条目上。

有几千个条目,这可能不会有很大的不同 - 但如果您有一个包含数百万或数十亿个条目和几个非聚集索引的表,则使用 16 字节 GUID 与 4 字节 INT 作为 PK 可能会所需空间的巨大差异 - 在磁盘和 RAM 中。

马克

于 2009-01-31T09:29:42.460 回答