优化SQL Server上的删除

pom*_*arc 41 sql sql-server

Deletesql server上的s有时很慢,我经常需要优化它们以减少所需的时间.我一直在寻找有关如何做到这一点的提示,我发现了各种各样的建议.我想知道你最喜欢和最有效的技术,以驯服删除野兽,以及它们的工作方式和原因.

到现在:

  • 确保外键有索引

  • 确保索引的条件

  • 用于 WITH ROWLOCK

  • 销毁未使用的索引,删除,重建索引

该你了.

Joh*_*som 22

您可能会对以下文章" 快速订购删除操作 "感兴趣.

执行快速SQL Server删除操作

该解决方案侧重于利用视图以简化为批量删除操作生成的执行计划.这是通过引用给定的表一次而不是两次来实现的,这反过来减少了所需的I/O量.

  • 在指定的链接上不再有原始文章,而是在此处以存档形式提供该链接:https://web.archive.org/web/20100212155407/http://blogs.msdn.com/sqlcat/archive/ 2009/05/21 / fast-ordered-delete.aspx(通过https://www.codelibrary.me/2012/08/01/perform-fast-mssql-delete-operations/向William Isted的提示) (2认同)

Eri*_*ler 15

我对Oracle有更多的经验,但很可能同样适用于SQL Server:

  • 删除大量行时,发出表锁,因此数据库不必执行大量行锁
  • 如果您删除的表被其他表引用,请确保其他表在外键列上有索引(否则数据库将对另一个表上的每个已删除行执行全表扫描,以确保删除行不违反外键约束)

  • 表锁会阻止对表的插入和更新,需要确保在其他事务开始超时之前删除很快. (2认同)

qui*_*ker 10

我想知道是不是垃圾收集数据库的时候了?您将行标记为删除,服务器稍后在扫描期间将其删除.你不希望每次删除都有这个 - 因为有时一行必须现在去 - 但它偶尔会很方便.

  • 删除行至少意味着三件事:a)确保删除没有违反外键约束b)将行占用的空间标记为"可用".c)从该表上的所有索引中删除该行.其中,a)可能是最昂贵的(如果引用表没有外键列的索引)但它应该立即完成,所以你可以告诉用户"你不能删除这一行,它仍然是引用".b)可能便宜而且c)通常不那么贵.因此,我不相信这个想法. (2认同)

xer*_*ero 8

2014-11-05答案摘要

这个答案被标记为社区维基,因为这是一个不断变化的主题,有很多细微差别,但整体上答案很少.

第一个问题是你必须问自己你正在优化的场景是什么?这通常是在db上具有单个用户的性能,或者在db上具有许多用户的扩展.有时答案恰恰相反.

对于单用户优化

  • 提示一个 TABLELOCK
  • 删除删除中未使用的索引,然后重建它们
  • 批量使用类似SET ROWCOUNT 20000(或其他任何东西,取决于日志空间)和循环(可能有一个WAITFOR DELAY),直到你摆脱它(@@ROWCOUNT = 0)
  • 如果删除一大部分表,只需创建一个新表并删除旧表
  • 对要删除的行进行分区,然后删除该分区.[阅读更多...]

用于多用户优化

  • 提示行锁
  • 使用聚集索引
  • 如果删除了大块,则设计聚簇索引以最小化页面重组
  • 更新"is_deleted"列,然后在维护窗口期间稍后进行实际删除

用于一般优化

  • 确保FK的源表上有索引
  • 确保WHERE子句有索引
  • WHERE使用视图或派生表标识要在子句中删除的行,而不是直接引用该表.[阅读更多...]


Chr*_*ter 5

说实话,从表中删除一百万行的方式与插入或更新一百万行一样严重.这就是行集的大小问题,你可以做的并不多.

我的建议:

  • 确保该表具有主键和聚簇索引(这对所有操作都至关重要).
  • 确保聚簇索引是这样的,如果要删除大块行,将发生最小页面重组.
  • 确保您的选择标准是SARGable.
  • 确保当前信任所有外键约束.

  • SARGable:在关系数据库中,如果DBMS引擎可以利用索引来加速查询的执行(使用索引搜索,而不是覆盖索引),则称查询中的条件(或谓词)是可搜索的.该术语源自Search ARGument Able的收缩.(维基百科) (10认同)