代码之家  ›  专栏  ›  技术社区  ›  roryok

SQL Server中是否需要主键?

  •  47
  • roryok  · 技术社区  · 14 年前

    这可能是一个相当幼稚和愚蠢的问题,但我还是要问它。

    我有一个表,有几个字段,其中没有一个是唯一的,还有一个主键,显然是。

    此表定期通过非唯一字段访问,但没有用户SP或进程通过主键访问数据。那么,是否需要主键?它是在幕后使用的吗?删除它会对性能产生积极或消极的影响吗?

    10 回复  |  直到 7 年前
        1
  •  39
  •   Aaron Digulla    14 年前

    必要吗?不。在幕后使用?嗯,它被保存到磁盘上并保存在行缓存中,等等。删除会稍微提高您的性能(注意使用毫秒精度的手表)。

    但是…下次有人需要创建对此表的引用时,他们会诅咒您。如果他们很勇敢,他们会添加一个pk(并等待很长时间让db创建列)。如果它们不是勇敢的或愚蠢的,它们将开始使用业务键(即数据列)创建引用,这将导致维护噩梦。

    结论:因为拥有一个pk(即使它不使用atm)的成本是如此之小,就让它成为吧。

        2
  •  12
  •   Remus Rusanu    14 年前

    你有没有外挂的钥匙,有没有参加过PK?

    如果此问题的答案是“否”,并且您的应用程序从不通过表的pk从表中检索项目,也不在WHERE子句中使用该项目,因此您只需添加一个标识列来拥有pk,那么:

    • pk本身没有增加值,但也没有损坏
    • 事实上,pk也很可能是聚集索引。 它取决于 .

    如果您有NC索引,那么您有一个窄的人工聚集密钥(标识pk)这一事实有助于保持这些索引窄(CDX密钥在每个NC叶槽中都会被复制)。因此,如果您有大量的NC索引,即使从未使用过PK,它也会很有帮助。

    另一方面,如果您有一个普遍的访问模式,那么一个比所有其他查询都重要的查询是频率和重要性,或者它是关键时间代码路径的一部分(例如,查询是在您站点上的每个页面访问上运行的,或者是每秒通过和应用程序等运行的),那么该查询是一个很好的候选者,可以指定聚集的键顺序。

    最后,如果表很少被查询,但经常被写入,那么它可能是堆的一个很好的候选者(根本没有聚集的键),因为堆在插入方面有很大的优势。见 Comparing Tables Organized with Clustered Indexes versus Heaps .

        3
  •  4
  •   SQLMenace    14 年前

    主键在幕后 clustered index (默认情况下,除非生成为非聚集索引)并保存表的所有数据。如果pk是标识列,则插入将按顺序进行,并且不会发生页拆分。

    但是如果您根本不访问ID列,那么您可能需要在其他列上添加一些索引。另外,当您有一个pk时,您可以设置fk关系

        4
  •  4
  •   onedaywhen    14 年前

    在逻辑模型中,表必须至少有一个键。没有理由随意指定其中一个键是“primary”;所有键都是相等的。虽然“主键”的概念可以追溯到特德·科德早期的工作,但这种错误早在关系理论中就被纠正了。

    悲哀地, PRIMARY KEY 找到了进入SQL的方法,从那时起我们就不得不接受它。如果考虑到 SELECT 查询也是一个表,那么SQL表也可以有重复的行。关系理论家非常讨厌SQL。但是,仅仅因为SQL允许您执行各种奇怪的非关系性操作,并不意味着您必须实际执行这些操作。是确保每个SQL表至少有一个键的良好实践。

    在SQL中,使用 主键 它本身就有影响,例如 NOT NULL , UNIQUE ,表对外键的默认引用。在SQL Server中,使用 主键 它本身就具有含义,例如表的聚集索引。但是,在所有这些情况下,隐式行为都可以使用特定的语法显式。

    你可以使用 独特的 (约束而不是索引)和 非空 结合使用以强制SQL中的键。因此,不,一个主键(甚至 主键 )在SQL Server中不需要。

        5
  •  3
  •   HLGEM    14 年前

    我永远不会有没有主键的表。假设您曾经需要删除一个副本-您将如何确定要删除哪个副本以及要保留哪个副本?

        6
  •  1
  •   Tom Gullen    14 年前

    定义的主键将有助于提高数据库中索引和关系的性能。

    在我的所有表中,我总是倾向于将主键定义为一个自动递增的整数,不管我是否访问它,这是因为当您开始扩展应用程序时,您可能会发现您确实需要它,并且它使生活变得更简单。

        7
  •  1
  •   Mitch Wheat    14 年前

    主键实际上是域模型的属性,它唯一标识域对象的实例。

    在每月递增的列(如标识列)上拥有聚集索引意味着不会发生页拆分,但插入会随着时间的推移使索引失衡,因此需要定期(或当碎片达到某个阈值时)重建索引。

    我必须有一个非常好的理由来创建一个没有主键的表。

        8
  •  1
  •   RBT    7 年前

    不需要pk。

    但是,您应该考虑在用于查询的列(即出现在WHERE子句中的列)上放置一个非唯一索引。这将大大提高查找性能。

        9
  •  0
  •   ProfessionalAmateur    14 年前

    如果您通过非关键字段访问它们,那么性能可能不会改变。不过,最好保留pk以备将来增强或与这些表的接口使用。您的应用程序是否只使用这一个表?

        10
  •  0
  •   marr75    14 年前

    正如sqlmanace所说,聚集索引是表的物理布局的一个重要列。此外,拥有一个聚集索引,特别是在像整数pk这样的瘦列上选择良好的索引,实际上可以提高插入性能。