为什么 DELETE 查询以一种格式运行的时间比另一种格式长得多?

xMR*_*MRi 11 performance sql-server execution-plan cardinality-estimates sql-server-2017 query-performance

我有特定的清理代码试图删除一些重复项。

这在许多客户站点上完美运行。日志告诉我此查询至少消耗了 1 秒到 45 秒:

DELETE FROM [tbl]
WHERE [Id] NOT IN
(
    SELECT MIN([Id])
    FROM [tbl]
    GROUP BY [IdProject], [IdRepresentative], [TimeStart]
) 
Run Code Online (Sandbox Code Playgroud)

但是我有一个客户,该查询运行了 4 个多小时(到现在为止还没有结束)!我检查了数据库 ( DBCC CHECKDB),我已经更新了统计信息 ( sp_updatestats),也UPDATE STATISTICS [tbl] WITH FULLSCAN显示没有变化。

我有来自客户的 DB 的原始备份。我在 SQL Server 14.0.2002.14 上运行它。我有标准版,客户用的是速成版。

我可以在活动监视器中看到没有其他人在使用数据库。没有等待,CPU 使用率为 25%(正好是我的 4 个 CPU 中的 1 个)。同样在我的测试用例中,没有其他人在使用数据库。

我重新查询并检查了以下语句:

DELETE FROM [tbl]
FROM [tbl] AS t
LEFT OUTER JOIN 
    (
        SELECT MIN([Id]) AS [IdMin]
        FROM [tbl]
        GROUP BY [IdProject], [IdRepresentative], [TimeStart]
    ) AS d ON d.[IdMin]=t.[Id]
WHERE d.[IdMin] IS NULL
Run Code Online (Sandbox Code Playgroud)

该语句在同一个数据库上执行只需 1-4 秒。

我可以用表或 SQL DB 做什么来加快速度?

对我来说,这似乎是 DB 情况/SQL Server 版本的特定问题。我们从未在近 100 个其他网站上看到过这种行为。

现在的问题是不是在讨论第二DELETEJOIN风格更好。我知道这个。但是我们目前正在生产其他代码,我无法即时更改它,但我想让客户满意。

Id不可为空。它是一个主要的集群 ID。创建索引不是一种选择。因为我无法影响当前运行的系统。某些东西必须在物理上有所不同。

绝对没有锁!我只是使用了一台带有数据库备份的独立机器。我只是在管理工作室内执行了这个单一的语句。

查询计划

查询计划

输出 sp_whoisactive

00 00:03:46.523;54;<?query -- DELETE FROM [tblSchedTimeline] WHERE [Id] NOT IN  (       SELECT MIN([Id])        FROM [tblSchedTimeline]         GROUP BY [IdProject], [IdRepresentative], [TimeStart]   )  --?>;DESKTOP-QV3K54L\Test;NULL;"            224,653";"                  0";"                  0";NULL;"          2,393,069";"                  0";"              1,225";"<ShowPlanXML xmlns=""http://schemas.microsoft.com/sqlserver/2004/07/showplan"" Version=""1.6"" Build=""14.0.2002.14""><BatchSequence><Batch><Statements><StmtSimple StatementText=""DELETE FROM [tblSchedTimeline]&#xD;&#xA;WHERE [Id] NOT IN&#xD;&#xA;&#x9;(&#xD;&#xA;&#x9;&#x9;SELECT MIN([Id])&#xD;&#xA;&#x9;&#x9;FROM [tblSchedTimeline]&#xD;&#xA;&#x9;&#x9;GROUP BY [IdProject], [IdRepresentative], [TimeStart]&#xD;&#xA;&#x9;)"" StatementId=""1"" StatementCompId=""1"" StatementType=""DELETE"" RetrievedFromCache=""true"" StatementSubTreeCost=""91.3449"" StatementEstRows=""257246"" SecurityPolicyApplied=""false"" StatementOptmLevel=""FULL"" QueryHash=""0x527453AF47051791"" QueryPlanHash=""0x1988C324845A2D73"" CardinalityEstimationModelVersion=""120""><StatementSetOptions QUOTED_IDENTIFIER=""true"" ARITHABORT=""true"" CONCAT_NULL_YIELDS_NULL=""true"" ANSI_NULLS=""true"" ANSI_PADDING=""true"" ANSI_WARNINGS=""true"" NUMERIC_ROUNDABORT=""false"" /><QueryPlan CachedPlanSize=""64"" CompileTime=""458"" CompileCPU=""16"" CompileMemory=""584""><MemoryGrantInfo SerialRequiredMemory=""512"" SerialDesiredMemory=""21608"" /><OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant=""104844"" EstimatedPagesCached=""26211"" EstimatedAvailableDegreeOfParallelism=""2"" MaxCompileMemory=""1414704"" /><OptimizerStatsUsage><StatisticsInfo LastUpdate=""2019-01-23T09:09:49.14"" ModificationCount=""37344"" SamplingPercent=""28.5972"" Statistics=""[PK__tblSched__3214EC076837DC08]"" Table=""[tblSchedTimeline]"" Schema=""[dbo]"" Database=""[AGVIP-KCC]"" /></OptimizerStatsUsage><RelOp NodeId=""0"" PhysicalOp=""Index Delete"" LogicalOp=""Delete"" EstimateRows=""257246"" EstimateIO=""7.9627"" EstimateCPU=""0.257246"" AvgRowSize=""9"" EstimatedTotalSubtreeCost=""91.3449"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList /><Update WithOrderedPrefetch=""1"" DMLRequestSort=""1""><Object Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Index=""[IDX_SchedTimeline_Ids]"" IndexKind=""NonClustered"" Storage=""RowStore"" /><RelOp NodeId=""2"" PhysicalOp=""Sort"" LogicalOp=""Sort"" EstimateRows=""257246"" EstimateIO=""0.0112613"" EstimateCPU=""21.2216"" AvgRowSize=""27"" EstimatedTotalSubtreeCost=""83.125"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></OutputList><MemoryFractions Input=""1"" Output=""1"" /><Sort Distinct=""0""><OrderBy><OrderByColumn Ascending=""1""><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /></OrderByColumn><OrderByColumn Ascending=""1""><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /></OrderByColumn><OrderByColumn Ascending=""1""><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></OrderByColumn><OrderByColumn Ascending=""1""><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OrderByColumn></OrderBy><RelOp NodeId=""3"" PhysicalOp=""Clustered Index Delete"" LogicalOp=""Delete"" EstimateRows=""257246"" EstimateIO=""30.7735"" EstimateCPU=""0.257246"" AvgRowSize=""27"" EstimatedTotalSubtreeCost=""61.8921"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></OutputList><Update WithOrderedPrefetch=""1"" DMLRequestSort=""1""><Object Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Index=""[PK__tblSched__3214EC076837DC08]"" IndexKind=""Clustered"" Storage=""RowStore"" /><RelOp NodeId=""5"" PhysicalOp=""Table Spool"" LogicalOp=""Eager Spool"" EstimateRows=""257246"" EstimateIO=""0.013125"" EstimateCPU=""0.0927087"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""30.8613"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OutputList><Spool><RelOp NodeId=""6"" PhysicalOp=""Nested Loops"" LogicalOp=""Left Anti Semi Join"" EstimateRows=""257246"" EstimateIO=""0"" EstimateCPU=""4.18e-006"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""30.7555"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OutputList><NestedLoops Optimized=""0""><OuterReferences><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OuterReferences><RelOp NodeId=""7"" PhysicalOp=""Sort"" LogicalOp=""Sort"" EstimateRows=""1"" EstimateIO=""0.0112613"" EstimateCPU=""0.000100011"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""29.3753"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OutputList><MemoryFractions Input=""1"" Output=""1"" /><Sort Distinct=""0""><OrderBy><OrderByColumn Ascending=""1""><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OrderByColumn></OrderBy><RelOp NodeId=""8"" PhysicalOp=""Nested Loops"" LogicalOp=""Left Anti Semi Join"" EstimateRows=""1"" EstimateIO=""0"" EstimateCPU=""1.07529"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""29.3639"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OutputList><NestedLoops Optimized=""0""><RelOp NodeId=""9"" PhysicalOp=""Index Scan"" LogicalOp=""Index Scan"" EstimateRows=""257246"" EstimatedRowsRead=""257246"" EstimateIO=""0.874977"" EstimateCPU=""0.283128"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""1.1581"" TableCardinality=""257246"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></OutputList><IndexScan Ordered=""1"" ScanDirection=""FORWARD"" ForcedIndex=""0"" ForceSeek=""0"" ForceScan=""0"" NoExpandHint=""0"" Storage=""RowStore""><DefinedValues><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></DefinedValue></DefinedValues><Object Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Index=""[IDX_SchedTimeline_Ids]"" TableReferenceId=""1"" IndexKind=""NonClustered"" Storage=""RowStore"" /></IndexScan></RelOp><RelOp NodeId=""10"" PhysicalOp=""Row Count Spool"" LogicalOp=""Lazy Spool"" EstimateRows=""1"" EstimateIO=""0"" EstimateCPU=""0.0001001"" AvgRowSize=""9"" EstimatedTotalSubtreeCost=""27.1305"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""257245"" EstimatedExecutionMode=""Row""><OutputList /><RowCountSpool><RelOp NodeId=""11"" PhysicalOp=""Filter"" LogicalOp=""Filter"" EstimateRows=""1"" EstimateIO=""0"" EstimateCPU=""0.0331891"" AvgRowSize=""9"" EstimatedTotalSubtreeCost=""1.38021"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList /><Filter StartupExpression=""0""><RelOp NodeId=""12"" PhysicalOp=""Stream Aggregate"" LogicalOp=""Aggregate"" EstimateRows=""69144"" EstimateIO=""0"" EstimateCPU=""0.18892"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""1.34702"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Column=""Expr1004"" /></OutputList><StreamAggregate><DefinedValues><DefinedValue><ColumnReference Column=""Expr1004"" /><ScalarOperator ScalarString=""MIN([AGVIP-KCC].[dbo].[tblSchedTimeline].[Id])""><Aggregate Distinct=""0"" AggType=""MIN""><ScalarOperator><Identifier><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></Identifier></ScalarOperator></Aggregate></ScalarOperator></DefinedValue></DefinedValues><GroupBy><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></GroupBy><RelOp NodeId=""13"" PhysicalOp=""Index Scan"" LogicalOp=""Index Scan"" EstimateRows=""257246"" EstimatedRowsRead=""257246"" EstimateIO=""0.874977"" EstimateCPU=""0.283128"" AvgRowSize=""27"" EstimatedTotalSubtreeCost=""1.1581"" TableCardinality=""257246"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></OutputList><IndexScan Ordered=""1"" ScanDirection=""FORWARD"" ForcedIndex=""0"" ForceSeek=""0"" ForceScan=""0"" NoExpandHint=""0"" Storage=""RowStore""><DefinedValues><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></DefinedValue><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /></DefinedValue><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /></DefinedValue><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></DefinedValue></DefinedValues><Object Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Index=""[IDX_SchedTimeline_Ids]"" TableReferenceId=""2"" IndexKind=""NonClustered"" Storage=""RowStore"" /></IndexScan></RelOp></StreamAggregate></RelOp><Predicate><ScalarOperator ScalarString=""[Expr1004] IS NULL""><Compare CompareOp=""IS""><ScalarOperator><Identifier><ColumnReference Column=""Expr1004"" /></Identifier></ScalarOperator><ScalarOperator><Const ConstValue=""NULL"" /></ScalarOperator></Compare></ScalarOperator></Predicate></Filter></RelOp></RowCountSpool></RelOp></NestedLoops></RelOp></Sort></RelOp><RelOp NodeId=""14"" PhysicalOp=""Filter"" LogicalOp=""Filter"" EstimateRows=""1"" EstimateIO=""0"" EstimateCPU=""0.0331891"" AvgRowSize=""9"" EstimatedTotalSubtreeCost=""1.38021"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList /><Filter StartupExpression=""0""><RelOp NodeId=""15"" PhysicalOp=""Stream Aggregate"" LogicalOp=""Aggregate"" EstimateRows=""69144"" EstimateIO=""0"" EstimateCPU=""0.18892"" AvgRowSize=""11"" EstimatedTotalSubtreeCost=""1.34702"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Column=""Expr1004"" /></OutputList><StreamAggregate><DefinedValues><DefinedValue><ColumnReference Column=""Expr1004"" /><ScalarOperator ScalarString=""MIN([AGVIP-KCC].[dbo].[tblSchedTimeline].[Id])""><Aggregate Distinct=""0"" AggType=""MIN""><ScalarOperator><Identifier><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></Identifier></ScalarOperator></Aggregate></ScalarOperator></DefinedValue></DefinedValues><GroupBy><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></GroupBy><RelOp NodeId=""16"" PhysicalOp=""Index Scan"" LogicalOp=""Index Scan"" EstimateRows=""257246"" EstimatedRowsRead=""257246"" EstimateIO=""0.874977"" EstimateCPU=""0.283128"" AvgRowSize=""27"" EstimatedTotalSubtreeCost=""1.1581"" TableCardinality=""257246"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row""><OutputList><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></OutputList><IndexScan Ordered=""1"" ScanDirection=""FORWARD"" ForcedIndex=""0"" ForceSeek=""0"" ForceScan=""0"" NoExpandHint=""0"" Storage=""RowStore""><DefinedValues><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></DefinedValue><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdProject"" /></DefinedValue><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""IdRepresentative"" /></DefinedValue><DefinedValue><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""TimeStart"" /></DefinedValue></DefinedValues><Object Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Index=""[IDX_SchedTimeline_Ids]"" TableReferenceId=""2"" IndexKind=""NonClustered"" Storage=""RowStore"" /></IndexScan></RelOp></StreamAggregate></RelOp><Predicate><ScalarOperator ScalarString=""[AGVIP-KCC].[dbo].[tblSchedTimeline].[Id]=[Expr1004]""><Compare CompareOp=""EQ""><ScalarOperator><Identifier><ColumnReference Database=""[AGVIP-KCC]"" Schema=""[dbo]"" Table=""[tblSchedTimeline]"" Column=""Id"" /></Identifier></ScalarOperator><ScalarOperator><Identifier><ColumnReference Column=""Expr1004"" /></Identifier></ScalarOperator></Compare></ScalarOperator></Predicate></Filter></RelOp></NestedLoops></RelOp></Spool></RelOp></Update></RelOp></Sort></RelOp></Update></RelOp></QueryPlan></StmtSimple></Statements></Batch></BatchSequence></ShowPlanXML>";"              2,705";runnable;"                  2";NULL;DESKTOP-QV3K54L;AGVIP-KCC;Microsoft SQL Server Management Studio - Abfrage;2019-02-05 15:35:50.680;2019-02-05 15:35:50.677;0;2019-02-05 15:39:37.297
Run Code Online (Sandbox Code Playgroud)

sp_spaceused 的输出

name    rows    reserved    data    index_size  unused
tblSchedTimeline    257246                  50280 KB    36432 KB    9720 KB 4128 KB
Run Code Online (Sandbox Code Playgroud)

Mar*_*ith 24

计划的这部分是问题所在。

在此处输入图片说明

问题

如果子查询带回 any,正确的行为NULL0NOT IN.

即使ID不可为空(因此在用作向量聚合时MIN(ID)不可能NULL),数据类型 ofMIN(ID)也被视为可空(例如,NULL当用作针对空表的标量聚合时,它仍然可以返回)。

因此,您将这个额外的行计数假脱机添加到计划中,其工作是确保(结合反半连接)如果NULL子查询返回a,则不会发出任何行。

不幸的是,即使被这个假脱机上的反半连接消除的行可能是0并且所有257,246行都将流向下一个运算符,基数估计将经过该步骤的估计行数减少到1

因此,它对嵌套循环内部的表进行了扫描,估计执行 1 次,而实际上它会扫描并聚合整个表的257,246时间。

来自 Anti Semi 连接的单行估计是一个已知的错误,很久以前在跟踪标志 4199 下已修复。有关更多背景和链接,请参阅反半加入错误的相关问答解决方法

解决方案

该错误仅在 SQL Server 2017 上为您显示,因为您选择了兼容性级别 120

您应该会发现您对带有跟踪标志 4199 活动的反半连接、OPTION (QUERYTRACEON 4199)提示、OPTION (USE HINT ('ENABLE_QUERY_OPTIMIZER_HOTFIXES'))提示(直接或通过计划指南)或数据库获得了更好的估计:

ALTER DATABASE SCOPED CONFIGURATION
SET QUERY_OPTIMIZER_HOTFIXES = ON;
Run Code Online (Sandbox Code Playgroud)

使用提示QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_140是 SQL Server 2017 CU10 的另一个选项。

您选择哪个选项取决于您希望优化器修补程序应用的范围。兼容性级别旨在是相当短期的事情,因此您应该计划移动到更新的设置,默认情况下此特定优化器修复处于启用状态。

再现

以下脚本重现了该问题并进行了修复:

ALTER DATABASE CURRENT 
SET COMPATIBILITY_LEVEL = 120;
GO
ALTER DATABASE SCOPED CONFIGURATION
SET QUERY_OPTIMIZER_HOTFIXES = OFF;
GO
DROP TABLE IF EXISTS dbo.tbl;
GO
CREATE TABLE dbo.tbl
(
    Id integer PRIMARY KEY, 
    IdProject integer NOT NULL, 
    IdRepresentative integer NOT NULL, 
    TimeStart datetime NOT NULL,

    INDEX i NONCLUSTERED
    (
        TimeStart, 
        IdRepresentative, 
        IdProject
    )
);
GO
UPDATE STATISTICS dbo.tbl 
WITH 
    ROWCOUNT = 257246, 
    PAGECOUNT = 25725;
Run Code Online (Sandbox Code Playgroud)
DELETE FROM [tbl]
WHERE [Id] NOT IN
(
    SELECT MIN([Id])
    FROM [tbl]
    GROUP BY [IdProject], [IdRepresentative], [TimeStart]
) 
OPTION 
(
    MAXDOP 1
);
Run Code Online (Sandbox Code Playgroud)

漏洞

DELETE FROM [tbl]
WHERE [Id] NOT IN
(
    SELECT MIN([Id])
    FROM [tbl]
    GROUP BY [IdProject], [IdRepresentative], [TimeStart]
) 
OPTION 
(
    MAXDOP 1,
    USE HINT ('ENABLE_QUERY_OPTIMIZER_HOTFIXES')
);
Run Code Online (Sandbox Code Playgroud)

带修复

替代语法

理想情况下,您还应该重写查询以不使用有问题的NOT IN. 一种可能的替代方案,即使使用上述修复也可能更有效,将是

DELETE T
FROM   (SELECT ROW_NUMBER() OVER (PARTITION BY IdProject, IdRepresentative, TimeStart ORDER BY Id) AS RN
        FROM   tbl) T
WHERE  RN > 1 
Run Code Online (Sandbox Code Playgroud)