在哪里放置主键

时间:2009-02-22 18:49:58

标签: sql sql-server-2008 indexing

据我所知,SQL Server 2008每个表只允许一个聚簇索引。为了这个问题,我们假设我有一个用户提交的故事列表,其中包含以下列。

ID(int,主键)
标题(nvarchar)
网址(nvarchar)
UniqueName(nvarchar)这是url slug(blah-blah-blah)
CategoryID(int,FK到Category表)

大部分时间故事都不会被ID查询。大多数查询将通过CategoryID或UniqueName完成。

我是索引的新手,所以我认为最好在这个表上放置2个非聚簇索引。一个在UniqueName上,另一个在CategoryID上。在对索引进行一些阅读之后,似乎对UniqueName上的聚簇索引非常有益。考虑UniqueName是...唯一的是将主键放在UniuqeName上并摆脱ID字段是否有利?对于CategoryID,我假设一个非聚集索引就可以了。

感谢。

5 个答案:

答案 0 :(得分:3)

首先,您可以将聚集索引放在唯一名称上,它不必位于id字段上。如果你很少或没有加入这个表,你可以摆脱id。无论如何,我会在唯一名称字段上放置一个唯一索引(您可能会发现它并不像您想象的那样独特!)。

如果你做了很多加入,我会保留id字段,它更小,更有效率加入。

由于你说自己是索引新手,我会指出虽然主键在定义时会自动创建索引,但外键却没有。您几乎总是希望索引外键字段。

答案 1 :(得分:1)

出于习惯,我总是创建一个身份字段“ID”,就像你拥有PK一样。它使事情保持一致。如果所有“主”表都有一个名为“ID”的字段,即INT标识,则PK总是很明显。另外,如果我需要创建一个桥实体,我将存储两个(或更多)INT类型的列而不是类型nvarchar()。因此,在您的示例中,我将ID保留为PK并在UniqueName上创建唯一索引。

答案 2 :(得分:1)

数据按群集密钥的顺序存储;如果您要按其中一个字段对数据进行密钥检索,那么使用该值假设值不会明显碎片化会更有利,这会降低插入性能。

另一方面,如果此表与ID上的很多表连接在一起,那么将聚簇键保留在PK上可能更有意义。

答案 3 :(得分:1)

根本没有要求或必须拥有聚簇索引,主键或其他方式。它是一种性能优化工具,与所有索引策略一样,应该在使用它时可以获得改进时应用。

如前所述,因为表是根据聚簇索引键进行物理排序的,所以它是Highlander情况:只能有一个!

聚簇索引主要用于以下情况:

  • 您经常需要检索一组给定列的值在一定范围内的行,因此通常是BETWEEN子句主题的列很有意义;或
  • 表中的大多数单行匹配发生在一个区域中,该区域可以通过键值的子集来描述。

我认为它们对于当顺序键是聚簇列时具有非常频繁插入的高容量事务系统时的情况特别无用。你会得到一大堆进程,试图插入同一个物理位置(一个“热点”)。事实证明,正如在编辑之前所评论的那样,我很遗憾地过时并显示我的年龄。请参阅this post on the topic by Kimberley Tripp,它说得更好。

顺序数字“ID”列通常不是好的候选列。如果仔细考虑,名称可以是好的,日期也是如此。

答案 4 :(得分:1)

通常,最好在身份密钥上索引表并将其用作聚簇索引。这里有一个简单的经验法则

不要将有意义的列用作主索引

原因是通常在有意义的列上使用PK会导致维护问题。这是一个经验法则,因此可以覆盖这样的情况,但通常最好是从(聚集的)无意义的标识列索引的每个表的假定默认位置开始工作。这对于连接来说往往更有效,并且因为它通常是大多数DBA将采用的默认设计,因此不会引起任何问题或提出任何问题,因为它们不像下一个DBA所假设的那样系统。毫无意义的PK总是更灵活,可以更容易地适应不断变化的环境,否则

何时覆盖规则?只有您确实设想了性能问题。对于在现代硬件上具有合理负载的大多数数据库,如果您没有通过聚类最佳索引来压缩最后一毫秒的性能,那么您将不会遇到任何麻烦。 DBA和程序员周期比CPU周期要昂贵得多,如果你只采用不同的策略来削减你的查询的奇数毫秒左右,那么它就是不值得的。但是,如果您正在查看接近一百万行的表格,那么这是另一回事。这在很大程度上取决于具体情况,但一般来说,如果我设计的数据库的行数少于100,000行,我将非常倾向于设计灵活性,易于编写稳定查询,以及其他设计人员期望看到的主体。超过一百万行,然后我设计性能。在10万到100万之间,这是一个判断问题。