【问题标题】:Best primary key format for large table大表的最佳主键格式
【发布时间】:2011-03-18 22:42:45
【问题描述】:

我正在开发一个 asp.net 应用程序,其中包含一些可能很大的数据表。我想知道定义主键的最佳方法是什么。我知道以前有人问过这个问题,但由于这是针对特定情况,我认为这个问题是有效的。

我在 SQL Server 2008 数据库上使用 Entity Framework 4。

考虑以下因素,定义主键有哪些可能性:

  1. 随着时间的推移,记录数很有可能会超过 32 位边界,因此无法使用自增整数。
  2. 无法在表中其他列的组合上定义主键。
  3. 出于数据同步的原因,应用程序生成的 ID 比数据库生成的 ID 更可取。此外,在 EF 中,这意味着需要额外往返数据库以检索新生成的 id。
  4. 为了提高插入性能,最好使用顺序键。
  5. 我认为(顺序)引导的空间要求是不利的。
  6. 对于字符串 ID,最好不区分大小写。

到目前为止,我自己想出的是一个自定义算法,它生成一个日期时间部分和一个随机部分,并转换为十六进制字符串表示。这给我留下了比 guid 略短的字符串。我仍然可以将其转换为 base64,但这会违反第 6 项。

感谢您的建议。

【问题讨论】:

  • "在 EF 中,这意味着需要额外往返数据库以检索新生成的 id。"错误的。 INSERT 和获取新 ID 在 EF 中的单个 SQL 语句中完成。
  • 同意 Craig - EF 很乐意在同一次往返中返回任何生成的 ID - 无需额外的往返 - 该论点没有实际意义
  • 啊,我不知道 EF 在同一往返中检索 id。不知道为什么我认为它不能。

标签: c# asp.net sql-server entity-framework sql-server-2008


【解决方案1】:

您可以考虑将密钥存储为BIGINT(8 字节整数)。

BIGINT 的工作方式与 INT 完全相同,并且可以以相同的方式用于自动递增的标识列。

【讨论】:

  • 我猜 bigint 效果最好。我将不得不以另一种方式解决数据迁移/同步问题。
  • 对于“数据同步”,也许您可​​以创建一个由 2 列组成的主键。 ID 的 1 列和机器名称的 1 列,或类似的东西?这样,ID 是增量的,您可以将其与多台机器同步,而不会出现关于重复键的错误。缺点是空间要求,因为它可能会占用更多空间作为 GUID。
【解决方案2】:

这里有几个想法。

  • 考虑大小为 5 或 6 字节的 binary 数据类型。
  • 不要忽视 partitioned tables 的好处,尤其是对于大型表。
  • 使剩余的列尽可能小。有时star schema 可以提供帮助。

很遗憾,您无法创建二进制数据标识列。但是,您可以使用 max(Id)+1 插入策略。我对 .NET 的实体框架不太熟悉,但应该有一种方法可以在同一次旅行中检索密钥。过去我看过文档解释如何将实体映射到存储过程并从中检索密钥,但我没有任何细节。

【讨论】:

  • 我认为在 EF 4.0 中,他们也添加了对将二进制密钥作为实体密钥的支持。我记得在 RC 的发行说明中看到了这一点。
【解决方案3】:

在您的情况下,我会使用顺序 GUID。

  • 它是一个代理键
  • 它是应用程序生成的,因此插入后无需检索数据库生成的 id
  • 它是顺序的,适用于聚集索引
  • 如果您可能会溢出 32 位密钥,那么您可能无论如何都必须使用 64 位密钥(除了您设法创建和使用 48 位密钥或类似的东西) - 那么 128 位 GUID 只需要两倍的空间
  • 字符串代理键对我来说有点不自然,我认为 GUID 键没有任何好处

【讨论】:

  • 我从来没有听说过应用程序能够生成伪顺序 GUID ..... 即便如此 - GUID = 16 字节,BIGINT = 8 字节 - 使用 GUID 仍然很浪费- 顺序与否。另外:空间浪费也被复制到表上的所有非聚集索引中,所以它比第一次看到的要糟糕得多
  • 阅读其他有关 GUID 键的帖子,我可能也会避免这种情况; stackoverflow.com/a/11938495/192305
猜你喜欢
  • 1970-01-01
  • 2013-04-13
  • 2015-10-24
  • 2021-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多