代码之家  ›  专栏  ›  技术社区  ›  Aaron Fischer

为主键选择数据类型时应该考虑什么?

  •  6
  • Aaron Fischer  · 技术社区  · 16 年前

    在创建新的数据库表时,选择主键的数据类型应考虑哪些因素?

    16 回复  |  直到 6 年前
        1
  •  11
  •   Community Navdeep Singh    7 年前

    很抱歉这么做,但我发现我对相关问题的答案(您可以查看 this this )可以应用于此。我对它们做了一点整形…

    你会发现很多关于这个问题的文章,你所做的每一个选择都有其优缺点。这些参数通常涉及关系数据库理论和数据库性能。

    在这个问题上,我的观点很简单: 代理主键始终有效 ,同时 自然钥匙可能不总是在这些天中的某一天起作用。 ,这有多种原因:字段太短、规则更改等。

    在这一点上,你已经猜到我基本上是uniqueidentifier/surrogate主键团队的一员,即使我欣赏并理解像这里介绍的那些论点,我仍然在寻找“自然”键比替代键更好的情况…

    除此之外,支持这一基本规则的最重要但始终被遗忘的论点之一与 代码规范化和生产力 :

    每次我创建一个表, 我要浪费时间吗

    1. 识别其主键及其物理特性(类型、大小)
    2. 每次我想在代码中引用这些特性时都要记住这些特性吗?
    3. 向团队中的其他开发人员解释我的pk选择?

    我的答案是否定的。 对于所有这些问题:

    1. 当代理选项给我一个防弹的解决方案时,我没有时间去尝试识别“最佳自然主键”。
    2. 我不想在编写代码时记住表的主键无论什么都是10个字符长的字符串。
    3. 我不想浪费时间讨论自然密钥长度:“如果你需要10个,为什么不取12个呢? 为了安全起见 “这个 “在安全方面” 争论真的让我恼火:如果你想保持安全的一面,这意味着你真的离不安全的一面不远!选择代理:它是防弹的!

    所以在过去的五年里,我一直在研究一个非常基本的规则:每个表(我们称之为“myTable”)都有其第一个字段名为 'id_MyTable' 它是唯一标识符类型。即使此表支持“多对多”关系,其中字段组合提供了一个非常可接受的主键,我还是希望创建此关系 'id_myManyToManyTable' 字段是唯一的标识符,只是为了遵守规则,最后,它不会受到伤害。

    主要的优点是,您不再需要关心在代码中使用主键和/或外键。一旦有了表名,就知道了pk的名称和类型。一旦知道在数据模型中实现了哪些链接,就可以知道表中可用外键的名称。

    如果你还想把你的“自然钥匙”放在桌子的某个地方,我建议你按照一个标准模型来构建它,比如

    Tbl_whatever
    
       id_whatever, unique identifier, primary key
       code_whatever, whateverTypeYouWant(whateverLengthYouEstimateTheRightOne), indexed
       .....
    

    其中id_u是主键的前缀,code_u用于“自然”索引字段。有些人认为代码域应该设置为唯一的。这是真的,可以通过DDL或外部代码轻松地管理它。注意,许多“自然”键都是计算出来的(发票号),因此它们已经通过代码生成了。

    我不确定我的规则是最好的。但这是一个非常有效的方法!如果每个人都在应用它,例如,我们可以避免浪费时间回答这种问题!

        2
  •  7
  •   Ely    16 年前

    如果使用数字键,请确保数据类型足够大,可以容纳表可能增长到的行数。

    如果使用guid,是否需要考虑存储guid所需的额外空间?对于应用程序的开发人员或用户来说,根据guid-pk进行编码会很痛苦。

    如果使用组合键,是否确定组合列始终是唯一的?

        3
  •  7
  •   Jan Gressmann    16 年前

    我真的不喜欢他们在学校教的东西,那就是使用“自然密钥”(例如图书数据库中的ISBN),甚至用两个或更多字段组成一个主键。我永远不会那样做。下面是我的小建议:

    • 在每个表中总是有一个专门的列作为主键。
    • 所有表中的列名称都应该相同,即“id”或“guid”
    • 尽可能使用guid(如果不需要性能),否则会增加ints

    编辑:
    好吧,我想我需要解释一下我的选择。

    • 为您的主键在所有表中都有一个相同的专用列名,这只会使您的SQL语句更容易构造,也更容易让其他人(可能不熟悉您的数据库布局)理解。尤其是当你做了很多连接和类似的事情。您不需要查找特定表的主键,您已经知道了,因为它在任何地方都是相同的。

    • guids和ints在大多数情况下并不那么重要。除非您达到guid的性能上限或进行数据库合并,否则您不会遇到任何重大问题。 但是 我喜欢吉他是有原因的。guid的全球独特性总有一天会派上用场。也许你现在不认为需要它,但是像,将数据库的某些部分同步到笔记本电脑/手机,甚至在不需要知道它们在哪个表的情况下找到数据记录,这些都是guid可以提供的优势的很好的例子。整数只标识一个表上下文中的记录,而guid则标识所有地方的记录。

        4
  •  6
  •   Galwegian    16 年前

    在大多数情况下,我使用identity int主键,除非场景需要大量复制,在这种情况下,我可以选择一个guid。

    我(几乎)从不使用有意义的钥匙。

        5
  •  4
  •   Noah Yetter    16 年前

    除非您有超方便的自然键可用,否则请始终使用数字类型的合成(即代理)键。即使您有一个可用的自然键,您可能还是要考虑使用一个合成键,并在您的自然键上放置一个额外的唯一索引。考虑到当联邦法律改变时,使用社会保障号码作为pks的更高级的ed数据库发生了什么,转换成合成密钥的成本是巨大的。

    此外,我不同意将每个主键命名为相同的做法,例如“id”。这使得查询更难理解,而不是更容易理解。主键应以表命名。例如employee.employee_id、affiliate.affiliate_id、user.user_id等。

        6
  •  2
  •   Jeffrey L Whitledge    16 年前

    不要使用浮点数字类型,因为不能正确比较浮点数字是否相等。

        7
  •  1
  •   Matthias Meid    16 年前
    • 你在哪里生成它?递增的数字不适合由客户机生成的密钥。
      • 您想要一个依赖于数据的或独立的密钥吗(有时您可以使用业务数据中的ID,不能说这是否总是有用的)?
      • 数据库能在多大程度上索引这种类型?

    到目前为止,我已经使用了uniqueidentifiers(guid)或递增整数。

    干杯 马蒂亚斯

        8
  •  1
  •   JohnMcG    16 年前

    在现实世界中有意义的数字通常是一个坏主意,因为现实世界经常会改变这些数字的使用规则,特别是允许重复的规则,然后你的手就会变得一团糟。

        9
  •  0
  •   Bob Probst    16 年前

    我倾向于使用生成的整数键。如果您希望数据库变得非常大,可以使用bigint。

    有些人喜欢用吉他。好处是,您可以合并数据库的多个实例而不更改任何键,但缺点是性能可能会受到影响。

        10
  •  0
  •   Tony Andrews    16 年前

    对于“自然”键,任何数据类型都适合列。人工(代理)键通常是整数。

        11
  •  0
  •   Pradeep    16 年前

    这要看情况而定。

    a)您是否可以使用唯一的顺序数字作为您的主键?如果是,那么选择uniqueidentifier作为主键就足够了。 b)如果您的业务需求是这样的,您需要有字母数字主键,那么您需要使用varchar或nvarchar。

    这是我能想到的两种选择。

        12
  •  0
  •   MartinHN    16 年前

    一个重要的因素是你要存储多少数据。我在一家网络分析公司工作,我们有很多数据。因此,pageviews表上的一个guid主键会杀死我们,因为它的大小。

    经验法则:为了获得高性能,您应该能够将整个索引存储在内存中。吉他很容易打破这个!

        13
  •  0
  •   Walter Mitty    16 年前

    在可以信任的情况下使用自然键。一些自然密钥的来源是不可信的。几年前,社会保障局偶尔会把同一个社会保障号码分配给两个不同的人。他们现在可能已经修好了。

    您可能可以信任车辆的VIN和书籍的ISBNs(但不能信任没有ISBN的小册子)。

    如果使用自然键,自然键将确定数据类型。

    如果您不能信任任何自然键,请创建一个合成键。为此,我更喜欢整数。留出足够的空间进行合理的扩建。

        14
  •  0
  •   Tom    16 年前

    我通常使用所有表的guid列主键(mssql中的rowguid)。什么可以是自然关键,我做了独特的约束。典型的例子是Produkt标识号,用户必须填写该标识号并确保其唯一性。如果我需要一个序列,比如在发票中,我构建一个表来保存最后一个数字和一个存储过程,以确保序列化访问。或者甲骨文中的一个序列:-)我讨厌自然钥匙的“社会保险号”样本,因为在注册过程中,自然钥匙的号码永远都无法使用。因此需要一个方案来生成假数字。

        15
  •  0
  •   Cœur N0mi    6 年前

    我通常使用整数,但这里有一个有趣的观点。

    https://blog.codinghorror.com/primary-keys-ids-versus-guids/

        16
  •  -1
  •   Kibbee    16 年前

    尽可能使用自然密钥的主键。例如,如果我有一个表,每天记录一条记录,那么logdate就是一个好的主键。否则,如果没有自然键,只需使用int。如果您认为将使用超过20亿行,则使用bigint。有些人喜欢使用guid,因为它们是独一无二的,所以效果很好,而且永远不会耗尽空间。但是,它们的长度不必要,如果您只是执行临时查询,则很难输入。