sql - 聚集索引 - 多部分索引与单部分索引以及插入/删除的影响

标签 sql sql-server indexing clustered-index

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

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

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

如果您能深入了解这个特定示例或指导我获取有关维护聚集索引的更多信息,我将不胜感激。

最佳答案

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

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

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

您需要一个窄键(最好是一个 INT),因为每个非聚集索引中的每个条目也将包含聚集键 - 您不想在聚集中放置大量列关键,你也不想把像 VARCHAR(200) 这样的东西放在那里!

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

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

Assume there is a table (Junk) and there are two queries that are done on the table, the first query searches by Name and the second query searches by Name and Something. As I'm working on the database I discovered that the table has been created with two indexes, one to support each query, like so:

这绝对没有必要 - 如果您在 (Name, Something) 上有一个索引,那么如果您仅搜索并限制 WHERE Name = ,则也可以使用该索引,而且效果也一样好abc - 完全不需要仅包含 Name 列的单独索引,而且只会浪费空间(并且需要时间来保持最新状态)。

所以基本上,你只需要在 (Name, Something) 上有一个索引,我同意你的观点 - 如果你在这个表上没有其他索引,那么你应该能够这是聚集键。由于该 key 不会不断增加并且也可能发生变化(对吗?),这可能不是一个好主意。

另一种选择是引入代理ID INT IDENTITY并对其进行聚类 - 有两个好处:

  • 这就是一个好的聚集键应该具备的一切,包括不断增加 -> 您永远不会遇到页面拆分和 INSERT 操作性能方面的任何问题
  • 您仍然可以获得拥有集群键的所有好处(请参阅 Kim Tripps 的博客文章 - 集群表几乎总是优于堆)

关于sql - 聚集索引 - 多部分索引与单部分索引以及插入/删除的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2924620/

相关文章:

sql - 如何查找违反参照完整性的记录

c# - 如何给 ADO.NET 参数

sql-server - 执行插入时的索引性能

sql-server - SQL Server 中唯一标识符列的聚集/非聚集索引

search - Solr 4.0存储和搜索Profile的Normalize数据

sql - 在 SQL Server 上的特定位置添加列?

mysql - 日期之间的条件选择

php - 我相信关于如何将信息插入数据库进行更新的查询存在错误

sql - 带加密的同步框架

sql-server - 将大量数据从一个表插入到另一个表的最快方法是什么? (SQL Server 2005)