Mik*_*ike 9 sql t-sql sql-server-2005
好的,我会尽力描述这个.我有一个SP,它传递XML并更新并插入另一个表.这在昨天工作.我今天改变的是使用OPENXML vs xml.nodes加载临时表.我甚至改回来了,我仍然得到这个有趣的问题.我有一个更新并插入同一个事务中.更新工作,然后插入挂起,没有错误没有任何...进行9分钟.通常需要10秒钟.没有阻止程序根据master.sys.sysprocesses.有趣的是,Select的Insert不返回任何行,因为它们已经存在于数据库中.更新更新72438 in
SQL Server Execution Times:
CPU time = 1359 ms, elapsed time = 7955 ms.
ROWS AFFECTED(72438)
Run Code Online (Sandbox Code Playgroud)
我不知道可能导致我的问题的原因是什么?权限我不这么认为?空间我不这么认为,因为会返回错误?
查询:
UPDATE [Sales].[dbo].[WeeklySummary]
SET [CountryId] = I.CountryId
,[CurrencyId] = I.CurrencyId
,[WeeklySummaryType] = @WeeklySummaryTypeId
,[WeeklyBalanceAmt] = M.WeeklyBalanceAmt + I.WeeklyBalanceAmt
,[CurrencyFactor] = I.CurrencyFactor
,[Comment] = I.Comment
,[UserStamp] = I.UserStamp
,[DateTimeStamp] = I.DateTimeStamp
FROM
[Sales].[dbo].[WeeklySummary] M
INNER JOIN
@WeeklySummaryInserts I
ON M.EntityId = I.EntityId
AND M.EntityType = I.EntityType
AND M.WeekEndingDate = I.WeekEndingDate
AND M.BalanceId = I.BalanceId
AND M.ItemType = I.ItemType
AND M.AccountType = I.AccountType
Run Code Online (Sandbox Code Playgroud)
和
INSERT INTO [Sales].[dbo].[WeeklySummary]
([EntityId]
,[EntityType]
,[WeekEndingDate]
,[BalanceId]
,[CountryId]
,[CurrencyId]
,[WeeklySummaryType]
,[ItemType]
,[AccountType]
,[WeeklyBalanceAmt]
,[CurrencyFactor]
,[Comment]
,[UserStamp]
,[DateTimeStamp])
SELECT
I.[EntityId]
, I.[EntityType]
, I.[WeekEndingDate]
, I.[BalanceId]
, I.[CountryId]
, I.[CurrencyId]
, @WeeklySummaryTypeId
, I.[ItemType]
, I.[AccountType]
, I.[WeeklyBalanceAmt]
, I.[CurrencyFactor]
, I.[Comment]
, I.[UserStamp]
, I.[DateTimeStamp]
FROM
@WeeklySummaryInserts I
LEFT OUTER JOIN
[Sales].[dbo].[WeeklySummary] M
ON I.EntityId = M.EntityId
AND I.EntityType = M.EntityType
AND I.WeekEndingDate = M.WeekEndingDate
AND I.BalanceId = M.BalanceId
AND I.ItemType = M.ItemType
AND I.AccountType = M.AccountType
WHERE M.WeeklySummaryId IS NULL
Run Code Online (Sandbox Code Playgroud)
UPDATE
尝试这里的建议工作了一段时间我在存储过程调用之前运行以下命令
UPDATE STATISTICS Sales.dbo.WeeklySummary;
UPDATE STATISTICS Sales.dbo.ARSubLedger;
UPDATE STATISTICS dbo.AccountBalance;
UPDATE STATISTICS dbo.InvoiceUnposted
UPDATE STATISTICS dbo.InvoiceItemUnposted;
UPDATE STATISTICS dbo.InvoiceItemUnpostedHistory;
UPDATE STATISTICS dbo.InvoiceUnpostedHistory;
EXEC sp_recompile N'dbo.proc_ChargeRegister'
Run Code Online (Sandbox Code Playgroud)
仍然停留在Insert语句,再次插入0行.
实际上只有少数事情可以发生,这里的技巧是按从最简单到最复杂的顺序消除它们。
第 1 步:手工制作一组要运行的 XML,它将生成一次插入且不会更新,因此您可以“回到基础”,并确定代码仍在执行您所期望的操作,并且结果正是如此你所期望的。这可能看起来很愚蠢或不必要,但你确实需要进行现实检查才能开始。
步骤 2:手工制作一组 XML,将生成一组中等大小的插入,但仍不进行更新。根据您对例行程序的经验,尝试找到可以在 3-4 秒内运行的程序。也许 5000 行。它是否继续按预期运行?
步骤 3:假设步骤 1 和 2 很容易通过,那么下一个最可能的问题是交易大小。如果您的更新在单个语句中达到 74,000 行,则 SQL Server 必须分配资源,以便能够在中止的情况下回滚所有 74,000 行。通常,您应该假设维护事务所需的资源(和时间)随着行数的增加而呈指数级增长。因此,再手工制作一组包含 50,000 行的插入件。您应该会发现这需要更多的时间。让它结束吧。是10分钟还是一个小时?如果花费很长时间但完成,则说明事务大小存在问题,服务器在尝试跟踪发生故障时回滚插入所需的所有内容时感到窒息。
步骤 4:确定整个存储过程是否在单个隐含事务中运行。如果是的话,情况就更糟了,因为 SQL Server 正在跟踪回滚 74,000 个更新和 ??? 所需的所有内容。插入到单个事务中。请参阅此页面:
http://msdn.microsoft.com/en-us/library/ms687099(v=vs.85).aspx
第 5 步:如果您有一个隐式交易,则可以选择其中之一。A) 关闭它,这可能会有所帮助,但不会完全解决问题,或者 B) 将存储过程分成两个单独的调用,一个用于更新,一个用于插入,以便至少两者处于不同的事务中。
第 6 步:考虑“分块”。这是一种避免交易成本爆炸式增长的技术。仅考虑 INSERT 让我们开始,您将插入包装到一个循环中,该循环在每次迭代内开始并提交一个事务,并在受影响的行为零时退出。INSERT 已被修改,以便您仅从源中提取前 1000 行并插入它们(1000 个数字是任意的,您可能会发现 5000 行会产生更好的性能,您必须进行一些实验)。一旦 INSERT 影响零行,就不再需要处理行,循环就会退出。
快速编辑:“分块”系统之所以有效,是因为大量行的完整吞吐量看起来像二次方。如果执行影响大量行的 INSERT,则处理所有行的总时间会激增。另一方面,如果您将其分解并逐行进行,则打开和提交每个语句的开销会导致所有行的总时间激增。在中间的某个位置,当您为每个语句“分块”出 1k 行时,事务要求处于最低水平,打开和提交语句的开销可以忽略不计,并且处理所有行的总时间是最短的。