【问题标题】:Should a table's primary key be a column in another index for that table?表的主键是否应该是该表的另一个索引中的列?
【发布时间】:2013-06-21 17:00:29
【问题描述】:

假设我有一张这样的桌子。 Id 是主键,所以我知道我得到了一个索引。

CREATE TABLE Employer
(
    Id VARCHAR(64) NOT NULL,
    EntityId VARCHAR(64) NOT NULL,
    Name VARCHAR(64) NOT NULL,
    Address1 VARCHAR(64) NOT NULL,
    Address2 VARCHAR(64) NOT NULL,
    City VARCHAR(64) NOT NULL,
    JobTitle VARCHAR(64) NOT NULL,
    StateCode VARCHAR(64) NOT NULL,
    ZipCode VARCHAR(64) NOT NULL,
    CONSTRAINT PK_Employer_Id PRIMARY KEY CLUSTERED (Id ASC)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

假设我添加了另一个索引来帮助进行一些特殊搜索(尽管原因并不相关)。是否有理由将 Id(主键)作为索引中的列之一包含在内? SQL 专家告诉我这是浪费空间,因为索引已经以某种方式包含主键。

CREATE INDEX [idxEmployerByNameAddress1City] on [Employer] ([EntityId], [Id], [Name], [Address1], [City])

【问题讨论】:

  • - 不要将VARCHAR(64) 设为您的聚集索引!这对性能来说真的非常糟糕...... SQL Server 表上的聚集索引应该很小(4-8 字节)和固定宽度(不是可变宽度,如VARCHAR(64)) - INT IDENTITY 几乎完美的。阅读 Kimberly Tripp's Ever-increasing clustering key – the Clustered Index Debate……….again! 博客文章以及她在聚集索引上发布的任何内容 - 她是 SQL Server 索引女王 - 听从她的建议!
  • 您的集群键(默认情况下是主键)将自动成为每个非聚集索引的一部分——这也是集群键应该很小且性能良好的另一个原因!但是单独添加ID 并不浪费空间——它无论如何都包含在该索引中,如果你明确指定它,SQL Serve 将不会复制它——>没有空间被浪费。
  • 我同意 VARCHAR(64) 的事情。在这一点上,对于我们的应用程序来说,这是一个遗留问题,实际上有一个半好的理由。所以现在很难改变。但在我们的应用程序的下一个版本中,我们计划切换到大整数或 guid。
  • 如果您要切换 - 不要切换到 GUID !再说一遍:Kimberly Tripp: GUIDs as PRIMARY KEYs and/or the clustering key - GUID 对于集群键来说是非常糟糕。避开他们。说真的。

标签: sql sql-server tsql indexing ddl


【解决方案1】:

如果您的二级索引不以主键列开头,则主键与二级索引无关。

另一方面,如果您的索引基于前两列是唯一的,就像这里的情况一样,那么在键中添加更多列是没有意义的 - 这只会浪费索引中的空间.

【讨论】:

  • 关于空间浪费的好点。将它们移至 INCLUDE 子句是否有意义?我相信这些列是该索引设计的查询的 SELECT 列表的一部分。
【解决方案2】:

索引有多种用途。其中之一是满足仅使用索引中的列的查询。所以,如果你有这样的查询:

select col, max(pk)
from t
group by col

并且您在t(col) 上有一个索引,那么查询必须从数据页中获取pk 的值。如果主键在索引中,则不需要原始数据页。

因此,在某些情况下,在索引中包含主键是个好主意。

顺便说一句,我完全同意主键不应该是 varchar(64) 的评论。我鼓励您使用整数主键,使用identity()。而且,出于某种原因,我认为拥有可变长度的主键是一个坏主意——可能是因为'A'' A'之间的混淆——它们是不同的,但在打印出来。

我会进一步指出,如果主键存储在其他表中,那么索引中浪费空间的问题就没有实际意义。您在存储如此大的主键时浪费了如此多的空间,以至于在索引中浪费更多的空间并不是什么大问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    • 2011-12-22
    • 2023-03-06
    • 2010-12-17
    • 2017-04-03
    相关资源
    最近更新 更多