删除性能的级联:删除一行其 1-Many 行的最快方法是啥?

Posted

技术标签:

【中文标题】删除性能的级联:删除一行其 1-Many 行的最快方法是啥?【英文标题】:Cascade on delete performance: Whats the fastest way to delete a row its 1-Many rows?删除性能的级联:删除一行其 1-Many 行的最快方法是什么? 【发布时间】:2009-09-16 14:07:55 【问题描述】:

我有一个数据库,其中有一个父“帐户”行,然后该行与另一个表具有 1-Many 关系,并且该表与另一个表具有 1-Many 关系。这进行了大约 6 个级别的深度(帐户位于顶部)。在最底部可能有数千(甚至可以超过 100k)行。在每个表上都有一个外键设置为在删除时级联。

问题是,如果我尝试删除最上面的一行(“帐户”),可能需要几分钟,有时甚至超过 10 分钟。是否有更快的方法来删除所有行(例如可能在单独的删除语句中从下到上)或者几乎是级联的?

我在服务器上使用 MSSQL 2005 和 MSSQL 2008,使用 L2S 来执行删除,但如果速度更快,我可以使用 T-SQL 语句。

我也尝试过从 SQL Management Studio 进行删除,但所需的时间也一样。

编辑:我们已经尝试重新索引数据库,差异可以忽略不计,可能只有一两分钟的差异。感谢您的所有回答,看来我将不得不开始编写一些代码来进行软删除!

【问题讨论】:

您是否在运行删除命令时查看了查询执行计划以确定瓶颈在哪里? 【参考方案1】:

删除就是删除,如果要删除大量行(100k),需要一段时间。

如果您执行软删除(例如,将状态设置为“D”),您可以运行作业以实际删除行,例如 1,000 左右的批次,随着时间的推移,它可能对您更有效。软删除应该只更新标题行并且会非常快。不过,您需要对应用程序进行编码以忽略这些“D”状态行及其子行。

编辑 进一步@Kane的评论。你只能做一个软删除,或者你可以做一个软删除,然后是一个批处理来做实际的删除,如果你真的想的话。如果驱动器空间不是问题,我会坚持使用软删除。

【讨论】:

进一步了解@KM 我强烈建议您阅读 Udi Dahan 关于删除数据的优秀文章:udidahan.com/2009/09/01/dont-delete-just-dont @Kane,不错的链接,我是软删除的忠实粉丝 另外,当用户打电话说他们错误地删除了某些内容时,软删除真的很好...... 我也同意软删除。我要做的唯一补充是,根据环境,我通常还会将“已删除”记录移到与原始记录相同的单独“存档”表中,以保持内容整洁并最小化表和索引大小.如果没有大量删除,我不会,但如果一个表经常“删除”,那么我会这样做。 @BBlake,这确实取决于环境。如果软删除数据上有很多外键,那么移动或实际删除数据就变得非常棘手。【参考方案2】:

您是否为所有外键编制了索引?这是一个常见问题。

【讨论】:

【参考方案3】:

听起来您可能有索引问题。

假设列 ParentId 上存在父子关系。根据定义,Parent 表中的 ParentId 列必须具有主约束或唯一约束,因此会被索引。但是,子表不需要在 ParentId 上建立索引。当您删除父条目时,SQL 必须删除子表中已分配该外键的所有行……如果该列未编入索引,则必须通过表扫描来完成工作。对于“删除链”中的每个表,这可能会发生一次。

当然,它可能只是音量。从具有多个索引的 100k+ 数据库中删除几 k 行,即使“删除查找”字段已被索引,也可能需要大量时间 - 如果您在删除期间有用户访问您的系统,请不要忘记锁定和阻塞!

正如 KM 所建议的,将删除推迟到计划维护窗口,这绝对是一种选择——尽管它可能需要对您的代码库进行认真的修改。

【讨论】:

以上是关于删除性能的级联:删除一行其 1-Many 行的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose中的级联样式删除

同一张表之间多对多的级联删除

没有级联删除目标的级联删除关系

sql 级联删除问题

如何在 EF 代码优先中禁用链接表的级联删除?

关于mysql的级联删除(之前好多人咨询过我)