为什么存储过程意外地在简单的DELETE语句上获得优化超时?

时间:2016-09-02 18:13:36

标签: sql-server performance stored-procedures

数据仓库中有一个多步骤过程,它生成一个临时表,其中包含将为每个批处理的作业列表。通常这是大约5,000个工作岗位。在财务汇总结束时,我们可能会查看约500,000条已处理的记录。我注意到它的一小部分正在给我一个关于存储过程的这部分优化的早期超时:

DELETE jfs    
FROM DataWarehouse.dbo.JobFinancialSummary jfs        -- Financials table (> 3,000,000 records with indices)
 INNER JOIN #JobList jl ON jfs.JobID = jl.JobID       -- List of Jobs being processed (avg. of 5,000 records)
 INNER JOIN FiscalPeriod fp ON fp.ID = jfs.FiscalPeriodID    -- Month Reference Table (about 1,000 records)
WHERE fp.[Status] IN (1,2)   -- Last 2 months

最令人困惑的是,这是存储过程中相对简单的部分,并且所有JOIN都在索引上。我唯一的问题是当优化器评估它时它是如何超时的。我的理解是,优化器为每个语句提供了自己的预算"但也许我错过了一些东西。为何超时?

2 个答案:

答案 0 :(得分:2)

删除的原因有很多:

原因:

  • 表可能包含CDC,已启用CT
  • 表可能包含在删除操作后工作的触发器
  • 表可能包含FK引用,约束
  • 表可能包含与该表关联的索引视图
  • 最重要的是我们需要检查这个表的交易方式等等,
  • 有很多方法可以删除,显然批量删除更快。首先,着名的方法是用软删除属性标记这些记录,并在夜间删除。

如果它将脱机删除,为了更快地删除,

然后捕获删除表的聚簇索引键

  • 禁用索引,FK' s,约束,因为您将在所有这些上功能性地照顾
  • 如果不需要,则禁用该表上的CT,CDC等 为索引视图创建脚本,然后删除与此表关联的索引视图
  • 然后通过批量删除,您可以通过设置@@ rowCount或top batchsize我们可以更快地删除任意数量的记录。

    DELETE TOP 50000 - 基于场景  FROM table1 在循环中

直接致电' CheckPoint'确保从事务日志中清除记录。还要确保您的恢复模式'是'简单'不是' Full' 如果它将在白天标记为在线删除,则作为软删除和在夜间作业中以非常小的批次运行删除

答案 1 :(得分:2)

隔离要删除的行/条目可能会更快,而不是在删除时加入。

这样的假设id是您的主要关键/身份:

IF OBJECT_ID('tempdb..#tmp') IS NOT NULL DROP TABLE #tmp

SELECT jfs.ID 
INTO #tmp
FROM DataWarehouse.dbo.JobFinancialSummary jfs        -- Financials table (> 3,000,000 records with indices)
INNER JOIN FiscalPeriod fp ON fp.ID = jfs.FiscalPeriodID    -- Month Reference Table (about 1,000 records)
WHERE fp.[Status] IN (1,2)
/*  EXISTS IS FASTER THAN A JOIN, AVOIDS FANNING */
AND EXISTS (SELECT 1 FROM #JobList jl where jfs.JobID = jl.JobID)       -- List of Jobs being processed (avg. of 5,000 records)

然后发出删除,例如:

DELETE TOP(1000) jfs
FROM DataWarehouse.dbo.JobFinancialSummary jfs 
WHERE EXISTS (SELECT 1 FROM #tmp t WHERE jfs.ID=t.ID)

从那里开始,根据您要删除的行数,您可能希望在一夜之间批量删除 - 超过5000行的任何内容都会升级为表锁,并且是批量删除的主要候选者。

我写了一篇关于如何在这里完成大批量删除的相当受欢迎的答案:

Deleting 1 millions rows in SQL Server