7

这个问题是关于在插入完成后重新组织聚集索引中的数据会发生什么。我认为在具有聚集索引的表上进行插入应该比没有聚集索引的表更昂贵,因为在聚集索引中重新组织数据涉及更改磁盘上数据的物理布局。除了通过我在工作中遇到的示例外,我不确定如何表达我的问题。

假设有一个表 (Junk),并且在表上执行了两个查询,第一个查询按名称搜索,第二个查询按名称和某事搜索。当我在处理数据库时,我发现该表已经创建了两个索引,一个用于支持每个查询,如下所示:

--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 的更新)。这有意义吗?我认为第二种索引方法会更好,因为这意味着需要维护的索引更少。

我将不胜感激对这个特定示例的任何见解或指导我了解有关维护聚集索引的更多信息。

4

3 回答 3

10

是的,当您的聚集索引不是最佳时,插入现有表(或其页面)的中间可能会很昂贵。最坏的情况是页面拆分:页面上的一半行必须移动到其他地方,并且索引(包括该表上的非聚集索引)需要更新。

您可以通过使用正确的聚集索引来缓解该问题 - 理想情况下是:

  • 窄(只有一个字段,尽可能小)
  • 静态(从不改变)
  • 唯一的(以便 SQL Server 不需要向您的行添加 4 字节的唯一性)
  • 不断增加(如 INT IDENTITY)

您需要一个窄键(理想情况下是单个 INT),因为每个非聚集索引中的每个条目也将包含聚集键 - 您不想在聚集键中放置很多列,也不你想把 VARCHAR(200) 之类的东西放在那里吗?

随着聚集索引的不断增加,您将永远不会看到页面拆分的情况。您可能遇到的唯一碎片来自删除(“瑞士奶酪”问题)。

查看 Kimberly Tripp 关于索引的 excellet 博客文章 - 最值得注意的是:

假设有一个表 (Junk),并且在表上执行了两个查询,第一个查询按名称搜索,第二个查询按名称和某事搜索。当我在处理数据库时,我发现该表已经创建了两个索引,一个用于支持每个查询,如下所示:

这绝对没有必要——如果你有一个索引(Name, Something),如果你搜索和限制只是,也可以使用该索引,也可以使用该索引——完全不需要只包含列WHERE Name = abc的单独索引,只会浪费空间(并且花费时间Name保持更新)。

所以基本上,你只需要一个索引(Name, Something),我会同意你的看法——如果你在这个表上没有其他索引,那么你应该能够使它成为聚集键。由于该密钥不会不断增加并且可能也会改变(对吗?),这可能不是一个好主意。

另一种选择是在其上引入代理ID INT IDENTITY和集群 - 有两个好处:

  • 它应该是一个很好的集群键,包括不断增加 -> 你永远不会遇到页面拆分和插入操作性能的任何问题
  • 您仍然可以获得拥有集群键的所有好处(请参阅 Kim Tripps 的博客文章 - 集群表几乎总是比堆更可取)
于 2010-05-27T20:31:54.807 回答
0

有人建议应该保留第一个索引方案,因为它会导致更有效的插入/删除

这是一个虚假的主张。有序数据是有序数据,会执行相同的 IO。

SET STATISTICS IO ON
-- your insert statement here
于 2010-05-28T13:40:52.797 回答
0

您只能在一个列上创建聚集索引,而不是两个或更多列,因此请选择您的应用程序主要查询的列,例如对客户全名的通配符查询等(参见讨论

于 2010-08-06T14:56:24.133 回答