我经常听到,虽然循环和游标一样糟糕,但我认为这不是真的。 从性能角度来看,从C#调用多个存储过程是否更好,或允许存储过程以循环方式解析XML数据和调用过程?是否有更好的方法在SQL中调用未知数量的存储过程而不是循环?
让我解释一下
我必须设计并实现供应商消息系统。有一家第三方公司将XML消息发送给收件人,该收件人来自发件人。我公司可能在任何时候都是发件人或收件人。
我想出了一个使用SQL while循环来运行存储过程的设计,但是我担心它在面对大量循环时可能表现不佳。
基本思路是: 发件人 - >第三方(消息系统) - >接收器
当我的公司是接收方时,我的问题可能会发生:
消息XML是这样的:
<envelope>
<to></to>
<from></from>
...
<messages>
<message>
<id></id>
...
<params>
<param>
<Name></Name>
<Value></Value>
<param>
...
</params>
</message>
...
</messages>
</envelope>
我可以在每次XML传输中接收或发送一条或多条消息。可能会立即收到多条消息。处理发送和接收XML的第三方公司的要求是我们总是以成功或失败来回应。我们有一个60秒的超时窗口来响应。由于这些限制,我自然害怕我不能在时间限制内完成我需要做的所有处理,导致超时。
因此,如果我在一次传输中找到消息1,2和3,我将必须运行存储过程1,2和3.我有一个临时表,其中包含消息ID和存储过程以运行。
因此,While循环基本上是(没有检查这部分的有效性,只是随心所欲,因为我没有SP方便)
While select count(*) from #temptable > 0
begin
select top 1 @idMessage = idMessage, @spToRun = spToRun from #temptable
exec @spToRun @idMessage
delete from #temptable where idMessage = @idMessage
select @idMessage = null, @spToRun = null
end
我害怕把它投入生产,然后发现它运行得太远,太慢了。有没有人有建议?
答案 0 :(得分:0)
我的建议是继续使用C#来解析xml并根据需要从dotnet端调用sprocs(只要你保持sql短而甜)。显然我并不完全熟悉你的情况,但从我的经验来看,它很难调试sql存储过程,特别是当它们在逻辑/处理方面很重,就好像你正在做的那样,即使你正在使用游标/循环。从c#这样的环境中控制更细粒度,您可以在执行处理时放置断点,在内存中监视变量的值(或者在xml节点中),并捕获更多种错误,这些错误在非常有用时非常有用。从第三方接收文件。另外,虽然你可能认为sql与dot net这样的中间件一样好,但它不是中间件,它通常最适合你的后端。通常在许多组织中,sql server在后端都有足够的功能,而且将来,如果你发现你已经过多地询问它并且它会开始对你表现得很奇怪,你可能会发现你的sql server负担过重。最后,就性能而言,我认为好处超过额外的行程时间,如果你保持sql简单并编译为存储过程,应该减轻,如果你把它放在生产服务器上,你应该有足够的内存。至少,如果我出于性能原因,我会偏向于C#/ dotnet,并依靠sql server做尽可能少的处理。
答案 1 :(得分:0)
最多1 MB的xml,我不会在存储过程中将其粉碎两次。 (你不会说xml中有多少行。)
您将获得比逐行发送更好的性能。
如果你有超过1 MB,请考虑使用goldie-locks方法。不要一个一个地发送它,不要发送它&#34;所有的东西&#34;,但是有一个外部的c#进程将xml分成更小的部分。例如:一个包含100,500行的文件,每次发送10,000封,发送11次。
您可以使用goldie-locks方法中的数字。
...
我会在C#中验证你的xml,然后我会把它发送到sql-server,就像我所说的那样#34; perfectXml&#34;,然后将它粉碎,也许变成#temp表,并从那里插入。再次,这是关键,xml应该是完美的&#34;从某种意义上说,你没有在tsql中运行检查以及if和this或那些语句。
按行划分Agonizing Row适用于鸟类。