使用 DELETE 逻辑不在嵌套查询中的最快性能 [重复]
Posted
技术标签:
【中文标题】使用 DELETE 逻辑不在嵌套查询中的最快性能 [重复]【英文标题】:Fastest performance with DELETE logic NOT IN nested query [duplicate] 【发布时间】:2013-04-19 03:17:37 【问题描述】:我正在尝试为这个 DELETE(和 SELECT)查询获得最快的性能。有没有更好的方法来删除记录,因为这需要 10 多分钟才能运行?我想它必须进行自己的排序和合并,直到找到记录为止。
SELECT COUNT([VISIT_ID])
FROM [dbo].[I2B2_SRC_VISITS]
WHERE [PATIENT_ID] NOT IN (
SELECT [PATIENT_ID] FROM [dbo].[I2B2_SRC_PATIENT]
)
DELETE FROM [dbo].[I2B2_SRC_VISITS]
WHERE [PATIENT_ID] NOT IN (
SELECT [PATIENT_ID] FROM [dbo].[I2B2_SRC_PATIENT]
)
编辑:我不能像使用 SELECT 那样将 DELETE 放在该查询的前面。但这是 DELETE 语句的最终结果。
DELETE FROM [dbo].[I2B2_SRC_VISITS]
WHERE [VISIT_ID] IN
(
SELECT a.[VISIT_ID]
FROM [dbo].[I2B2_SRC_VISITS] a
LEFT JOIN [dbo].[I2B2_SRC_PATIENT] b
ON a.[PATIENT_ID] = b.[PATIENT_ID]
WHERE b.[PATIENT_ID] IS NULL
)
【问题讨论】:
ExplainExtended BlogSQLAuthority 和许多其他在线文献将引导您走向您已经写过的不存在/不存在。但是,总是有例外,例如当您没有必要的索引时(有时可能是有效的)。始终尝试尽可能多的形式,并使用最有效的形式。不过,对于小型数据集,这可能无关紧要。 【参考方案1】:通过JOIN
来做怎么样?
DELETE a
FROM [dbo].[I2B2_SRC_VISITS] a
LEFT JOIN [dbo].[I2B2_SRC_PATIENT] b
ON a.[PATIENT_ID] = b.[PATIENT_ID]
WHERE b.[PATIENT_ID] IS NULL
确保两个表中的 [PATIENT_ID]
列都有键定义,这样会更快。
没错。 NOT EXIST
更好。
DELETE a
FROM [dbo].[I2B2_SRC_VISITS] a
WHERE NOT EXISTS
(
SELECT 1
FROM [dbo].[I2B2_SRC_PATIENT] b
WHERE a.[PATIENT_ID] = b.[PATIENT_ID]
)
【讨论】:
也可以使用NOT EXIST
试试这个语法:DELETE a FROM [dbo].[I2B2_SRC_VISITS] a WHERE NOT EXIST ( SELECT 1 FROM [dbo].[I2B2_SRC_PATIENT] b WHERE a.[PATIENT_ID] = b.[PATIENT_ID] )
可能 - 行数不足以达到临界点。见sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join
@JW 你确定他们是同一个计划吗?我看到一个带有 NOT EXISTS 和反半连接的额外 TOP 运算符。另一个具有 LEFT OUTER JOIN,看起来它实现了行和随后的过滤器。根据问题检查我评论中的第一个链接。
@AaronBertrand 对。就在这里。 NOT EXISTS
更好sqlfiddle.com/#!3/244f5/1
@JW 一个提示。对于这样的 2 个查询,尽管查询优化器会发出所有不准确和谎言,但您可以通过将其设为单个批次来查看它们的相对估计成本,例如sqlfiddle.com/#!3/244f5/2/0。 (单一)计划同时显示了两个查询,现在更容易比较成本。以上是关于使用 DELETE 逻辑不在嵌套查询中的最快性能 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何提高 SQL Server 查询的性能以选择具有值的行不在子查询中的一次计数