这个问题是关于插入完成后重组聚簇索引中的数据会发生什么。我假设在具有聚簇索引的表上执行插入应该更昂贵,因为重组聚簇索引中的数据涉及更改磁盘上数据的物理布局。我不知道如何通过我在工作中遇到的一个例子来表达我的问题。
假设有一个表(垃圾),并且在表上有两个查询,第一个查询按名称搜索,第二个查询按名称搜索。当我正在处理数据库时,我发现该表已经创建了两个索引,一个用于支持每个查询,如下所示:
--drop table Junk1
CREATE TABLE Junk1
(
Name char(5),
Something char(5),
WhoCares int
)
CREATE CLUSTERED INDEX IX_Name ON Junk1
(
Name
)
CREATE NONCLUSTERED INDEX IX_Name_Something ON Junk1
(
Name, Something
)
现在,当我查看这两个索引时,似乎IX_Name是多余的,因为任何希望按名称搜索的查询都可以使用IX_Name_Something。所以我将消除IX_Name并使IX_Name_Something成为聚集索引:
--drop table Junk2
CREATE TABLE Junk2
(
Name char(5),
Something char(5),
WhoCares int
)
CREATE CLUSTERED INDEX IX_Name_Something ON Junk2
(
Name, Something
)
有人建议应该保留第一个索引方案,因为它会导致更高效的插入/删除(假设不需要担心Name和Something的更新)。那会有意义吗?我认为第二种索引方法会更好,因为它意味着需要维护一个较少的索引。
我希望能够深入了解这个具体的例子,或者向我介绍有关维护聚簇索引的更多信息。
答案 0 :(得分:9)
是的,当您的聚簇索引不是最佳时,插入现有表(或其页面)的中间可能会很昂贵。最糟糕的情况是页面拆分:页面上的一半行必须移动到其他地方,并且需要更新索引(包括该表上的非聚集索引)。
您可以使用正确的聚簇索引来缓解该问题 - 理想情况是:
您需要一个窄键(理想情况下是一个INT),因为每个非聚集索引中的每个条目都将包含聚类键 - 您不希望在聚类中放置大量列键,你也不想把VARCHAR(200)放在那里!
随着聚簇索引的不断增加,您将永远不会看到页面拆分的情况。您可能遇到的唯一碎片来自删除(“瑞士奶酪”问题)。
查看Kimberly Tripp关于索引的excellet博客文章 - 最值得注意的是:
假设有一个表(垃圾)和 有两个查询已完成 该表,第一个查询搜索 名称和第二个查询搜索 名字和东西。正如我正在努力的那样 数据库我发现了 表已创建两个 索引,一个支持每个查询, 像这样:
这绝对没有必要 - 如果你在(Name, Something)
上有一个索引,那么如果你只搜索和限制WHERE Name = abc
那个索引也可以使用 - 只有一个单独的索引完全不需要Name
列,只会浪费空间(并且需要花费时间来保持最新)。
所以基本上,你只需要(Name, Something)
上的一个索引,我同意你的看法 - 如果你在这个表上没有其他索引,那么你应该能够将它作为聚簇密钥。由于这个密钥不会不断增加并且可能也会改变(对吧?),这可能不是一个好主意。
另一种选择是引入代理ID INT IDENTITY
和群集 - 有两个好处:
答案 1 :(得分:0)
有人建议应该保留第一个索引方案,因为它会导致更有效的插入/删除
这是一个虚假的主张。有序数据是有序数据,将执行相同的IO。
SET STATISTICS IO ON
-- your insert statement here
答案 2 :(得分:0)
您只能在一列上创建聚簇索引,而不是两列或更多列,因此请选择您的应用主要查询的列,例如客户全名的通配符查询等(请参阅discussion)