【问题标题】:SQL Server - Clustered index design for dictionarySQL Server - 字典的聚集索引设计
【发布时间】:2011-04-20 10:17:35
【问题描述】:

希望得到一些建议。我有一张表,我想在其中跟踪一个对象以及与该对象相关的键列表。示例:

OBJECTID   ITEMTYPE   ITEMKEY
--------   --------   -------
1          1          THE
1          1          BROWN
1          2          APPLE
1          3          ORANGE
2          2          WINDOW

OBJECTID 和 ITEMKEY 都具有高选择性(即 OBJECTID 和 ITEMKEY 变化很大)。我的访问方式有两种:

  • 按 OBJECTID:每次对象更改时,键列表都会更改,因此需要基于 OBJECTID 的键。变化频繁发生。

  • 按 ITEMKEY:这是用于关键字搜索,也经常发生。

所以我可能需要两个键,并为聚集索引选择一个(访问更频繁的一个,或者我希望速度达到的位置,现在假设我将优先考虑 OBJECTID 用于聚集索引)。我很困惑的是我应该如何设计它。

我的问题是,哪个更好:

a) (OBJECTID,ITEMTYPE,ITEMKEY) 的聚集索引,然后是 (ITEMKEY) 的索引。我担心的是,由于聚集索引非常大(2 个整数,1 个字符串),因此索引会很大,因为所有索引项都必须指向聚集键。

b) 创建一个以运行标识 DIRECTORYID (integer) 作为主键和聚集索引的新列,并为 (OBJECTID,ITEMTYPE,ITEMKEY) 和仅 (ITEMKEY) 声明两个索引。这将最小化索引空间,但查找成本更高。

c) (OBJECTID,ITEMTYPE,ITEMKEY) 的聚集索引,以及 (ITEMKEY,ITEMTYPE,OBJECTID) 的物化视图。我的逻辑是,这避免了键查找,并且仍然与在 a) 中查找的索引一样大,但开销更高。

d) Err...根据要求,也许有更好的方法?

提前致谢, 安德鲁

【问题讨论】:

  • 为什么你认为你需要集群在(OBJECTID,ITEMTYPE,ITEMKEY)而不是(OBJECTID)上?
  • 如果您尝试在 SQL Server 中构建高性能关键字搜索,您应该考虑全文搜索:msdn.microsoft.com/en-us/library/ms142583.aspx
  • @Lucero:集群键必须是唯一的 - 而 ObjectId 不是。在这种情况下,SQL Server 将为您的索引条目添加一个四字节的唯一性 - 您可以通过为集群键选择一个真正唯一的列 (INT IDENTITY) 来避免这种情况。
  • @marc_s:鉴于此问题中的列选择,我认为隐式生成的唯一整数列应该比大多数其他组合更好。当然,如果唯一索引上的聚类匹配很好,则应该使用它,但恕我直言,这里没有。
  • @Lucero:感谢您的 cmets,我明白您的意思,但如果 SQL 无论如何要添加它,我不妨添加自己的身份/pk/clusterkey,例如(OBJECTID,DIRECTORYID) 以便在需要时可以将其用作单个唯一键(因为无法访问隐藏的 SQL)。但是我同意你的观点,如果我想要通过 OBJECTID 进行聚类,这将比使用 (OBJECTID,iTEMTYPE,ITEMKEY) 更好。

标签: sql sql-server database-design clustered-index


【解决方案1】:

如果可能的话,尽量保持你的聚集键尽可能小,因为它也会被添加到你表上的所有非聚集索引中。

因此,如果可能的话,我会使用一个 INT,或者可能是两个 INT 的组合 - 但肯定不会是 VARCHAR 列 - 特别是如果该列可能很宽(> 10 个字符)并且一定会改变。

所以在你提出的选项中,我个人会选择 b) - 为什么??

添加代理 DirectoryID 将满足集群键的所有关键标准:

  • 稳定
  • 独一无二的
  • 不断增加

您的其他非聚集索引受到的影响最小。

请参阅 Kimberly Tripp 的 outstanding blog post,了解在 SQL Server 表上选择良好集群键的主要标准 - 非常有用且很有启发性!

为了满足您的查询要求,我将添加两个非聚集索引,一个在 ObjectID(可能包括其他经常需要的列)上,另一个在 ItemKey 上按键名搜索。

【讨论】:

  • 感谢您指出帖子,它很有启发性(尝试按最常用的内容进行聚类似乎更直观,但从文章来看,似乎在现实世界的情况下,还有其他开销参与,这使得在集群密钥上遵循这些规则更好!)
  • marc_s:我有一个问题想请教您的意见:使用 (OBJECTID,DirectoryID) 作为集群键是否有意义?这至少会使其按照一个标准进行集群,同时保持集群键较小(但会丢失始终在表属性末尾插入)。值得吗,你会在你的设计中这样做吗?
  • @andrwo:如果 DirectoryID 将是一个 INT IDENTITY 列,那么我将只在这个单一的 INT 上进行集群 - 没有必要将第二个 INT 添加到集群索引中,真的 - 或者你为什么想要这样做??
  • @marc_s:纯粹出于性能原因,由于表很大,认为它会在通过 OBJECTID 访问时缩短书签查找(因为如果按 (DirectoryID) 集群,SQL 服务器仍然需要查找每个项目改变它)。实际上,根据我想要最大化的内容(集群索引碎片、空间、更新性能),两种方式都有争论,但我只是在调查一般意见,看看数据库设计人员是否通常会做这种事情,或者他们通常会尽力坚持递增整数身份集群规则。感谢您迄今为止的帮助!
  • @andrwo:如果您想减少书签查找,请在您要搜索的列上创建一个非聚集索引,并包括任何其他有意义的列。除非绝对必要,否则我不会“污染”聚集索引,这对于在某些方面具有良好性能至关重要......
猜你喜欢
  • 2011-10-07
  • 1970-01-01
  • 2012-10-01
  • 2018-05-08
  • 2014-12-21
  • 2011-06-02
  • 2011-05-13
  • 2010-11-23
相关资源
最近更新 更多