SQL Server索引成本

时间:2010-04-04 20:22:33

标签: sql-server performance indexing

我已经读过在SQL Server中添加表索引的权衡之一是插入/更新/删除查询的成本增加,有利于选择查询的性能。

我可以从概念上理解在插入的情况下会发生什么,因为SQL Server必须将条目写入与新行匹配的每个索引中,但更新和删除对我来说更加模糊,因为我无法完全理解围绕数据库引擎必须做什么。

我们以DELETE为例,假设我有以下模式(请原谅伪SQL)

TABLE Foo
 col1 int
,col2 int
,col3 int
,col4 int
PRIMARY KEY (col1,col2)

INDEX IX_1
col3
INCLUDE 
col4

现在,如果我发出声明

DELETE FROM Foo WHERE col1=12 AND col2 > 34

我理解引擎必须做什么才能更新表(如果您愿意,还可以使用聚簇索引)。设置索引是为了便于查找要删除的行范围,并执行此操作。

但是,此时它还需要更新IX_1并且我给它的查询没有给数据库引擎找到要更新的行的明显有效方法。是否被迫在此时进行完整的索引扫描?引擎是否首先从聚簇索引中读取行并对索引生成更智能的内部删除?

如果我更清楚地知道幕后发生的事情,我可以帮助我解决这个问题,但我想我的真正问题是这个。我有一个数据库,它花了很多时间在删除,我试图弄清楚我能做些什么。

当我显示删除的执行计划时,它只显示表Foo上的“Clustered Index Delete”条目,该条目在详细信息部分列出了需要更新的其他索引但我没有得到任何指示这些其他指数的相对成本。

在这种情况下他们都是平等的吗?有没有什么方法可以估算去除一个或多个这些指数的影响而不必实际尝试呢?

1 个答案:

答案 0 :(得分:3)

非聚集索引store the clustered keys 它不必进行全面扫描,因为:

  • 您的查询将使用聚集索引来查找行
  • 行包含其他索引值(c3)
  • 使用其他索引值(c3)聚集索引值(c1,c2),它可以找到其他索引中的匹配条目。

(注意:我在解释文档方面遇到了麻烦,但我认为你的案例中的IX_1可以被定义为好像它也在c1,c2上排序。因为这些已经存储在索引中,所以它会很有意义使用它们来更有效地查找记录,例如更新和删除。)

所有这些都需要付出代价。对于每个匹配的行:

  • 必须读取行,找出c3的值
  • 必须在非聚集索引中找到(c3,c1,c2)的条目
  • 它也必须从那里删除条目。

此外,虽然范围查询在您的情况下对聚簇索引有效(线性访问,找到匹配后),但维护其他索引很可能会导致随机访问每个匹配行的 。随机访问的成本远高于仅从给定匹配开始枚举B+ tree叶节点的成本 鉴于上述查询,在非聚集索引维护上花费的时间更多 - 数量在很大程度上取决于col1 = 12 AND col2 > 34 谓词选择的记录数。

我的猜测是,成本在概念上与您没有二级索引但成本相同。一个单独的表,将(c3,c1,c2)保存为聚簇键中的唯一列,并使用(c3,c1,c2)为每个匹配行执行DELETE。显然,索引维护是SQL Server内部的并且速度更快,但从概念上讲,我猜上面的内容很接近。

以上意味着索引的维护成本将保持非常接近,因为每个二级索引中的条目数相同(记录数),并且每个索引的删除只能一个接一个地进行索引。

如果您需要索引,性能方面,取决于已删除记录的数量,您可能最好安排删除,删除索引(删除期间未使用的索引) - 删除之前并在之后添加它们。根据受影响的记录数量,重建indexes might be faster