Clustered vs Non-Clustered

24 浏览
0 Comments

Clustered vs Non-Clustered

我对 SQL(Server 2008)的基础知识有限,现在正被我们的 DBAs 所挑战。让我解释一下情况(我已经提到了一些显而易见的陈述,希望我是对的,但如果你看到有什么不对的,请告诉我):

我们有一个用于保存人们法院命令的表格。当我创建这个表格(名称:CourtOrder)时,它是这样创建的:

CREATE TABLE dbo.CourtOrder
(
  CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
  PersonId INT NOT NULL,
  + around 20 other fields of different types.
)

然后,我对主键应用了一个非聚集索引(为了提高效率)。我这样做的原因是它是一个唯一的字段(主键),应该被索引,主要是为了选择的目的,因为我们经常使用 Select from table where primary key = ...

然后,我在 PersonId 上应用了一个聚集索引。原因是为了将一个特定人的命令物理地分组,因为大部分工作都是为一个人获取命令。所以,select from mytable where personId = ...

现在他们指出我犯了一个错误。他们告诉我,我们应该在主键上放置聚集索引,而在 personId 上放置普通索引。这对我来说似乎非常奇怪。首先,为什么要在一个唯一的列上放置聚集索引?它正在进行聚集?这肯定是浪费聚集索引?我本来认为普通索引应该用于一个唯一的列上。此外,聚集索引意味着我们不能聚集不同的列(每个表一个,对吗?)。

他们认为我犯错的原因是,他们相信将 PersonId 上的聚集索引会使插入操作变慢。为了提高 5% 的选择速度,我们将获得 95% 的插入和更新速度下降。这是否正确和有效?

他们说因为我们将personId聚类,所以每当我们插入或更改PersonId时,SQL Server都必须重新排列数据。

于是我问,为什么SQL会有聚集索引的概念,如果这样很慢?它的速度和他们所说的一样慢吗?我该如何设置索引以实现最佳性能?我曾经认为SELECT被使用得比INSERT多...但他们说我们在INSERT上遇到了锁定问题...

希望有人能帮助我。

admin 更改状态以发布 2023年5月21日
0
0 Comments

我绝对不是SQL专家...所以请把这个看作开发者的视角而不是DBA的视角...

在未按顺序插入聚集(物理有序)索引时,插入/更新会导致额外的工作量。此外,如果您有多个插入同时发生并且它们都发生在同一个位置上,那么您将面临争用。您的具体性能取决于您的数据及其访问方式。一般的经验法则是在表中构建聚集索引时,在最唯一的狭窄值上(通常是PK)。

我假设您的PersonId不会更改,因此此处不涉及更新。但是,考虑一下PersonId为1、2、3、3、4、5、6、7、8、8的几行快照。

现在插入20个新行,PersonId为3。首先,由于这不是唯一键,服务器会添加一些额外字节到您的值(在幕后)以使其唯一(这还会增加额外的空间),然后必须更改这些行所在的位置。将其与插入自动增量PK进行比较,插入发生在末尾。非技术性解释可能会归结为这一点:如果是在表末端自然顺序递增的较高值,则需要做的“叶子重排”工作较少,而插入您的项目时不需要重新调整该位置上现有项目的位置。

现在,如果您在插入方面遇到问题,则很可能是一次插入了许多相同或相似的PersonId值,这将导致在整个表中各个位置上有额外的工作,并且碎片化会导致性能下降。在您的情况下,切换到以PK为聚集索引的缺点是,如果您今天在分布在表中的值不同的PersonIds上遇到插入问题,如果您将聚集索引切换到PK并且现在所有插入都发生在一个位置,则由于集中争用的增加,可能会使您的问题实际上变得更糟。(另一方面,如果您今天的插入不是分散在各处,而是通常聚集在相似的区域,则通过将聚集索引从PersonId切换到PK,您的问题可能会得到缓解,因为您将最小化碎片化。)

您的性能问题应根据您的独特情况进行分析,将这些类型的答案仅作为一般指南。您的最佳选择是依靠可以验证您的问题所在的DBA。听起来您有资源争用问题,可能超出了简单索引调整的范围。这可能是更大问题的症状。(可能是设计问题...否则是资源限制。)

无论如何,祝您好运!

0
0 Comments

聚集索引与非聚集索引的区别在于聚集索引决定了数据库中行的物理顺序。换句话说,将聚集索引应用于 PersonId 意味着表中的行将按 PersonId 物理排序,可以在此索引搜索中直接跳转到行(而非非聚集索引,该索引会将您引导到行的位置,增加了额外的步骤)。

话虽如此,主键不是聚集索引并不常见,但也不是没有。您的情况中问题与您所假设的相反:您需要在聚集索引中具有唯一值,而不是重复值。因为聚集索引决定了行的物理顺序,如果索引在一个非唯一列上,则服务器必须向具有重复键值的行(在您的情况下,任何具有相同 PersonId 的行)添加一个后台值,使得组合值(键 + 后台值)是唯一的。

我唯一建议的是不要将代理键(您的 CourtOrderId)列作为主键,而是使用 PersonId 和一些其他唯一标识列或一组列作为复合主键。如果这不可能(或不切实际),则将聚集索引放在 CourtOrderId 上。

0