2015-09-14 37 views
0

我经常听说while循环和游标一样糟糕,我不认为这是真的。 从性能的角度来看,从C#调用多个存储过程还是允许存储过程以循环方式解析XML数据和调用过程会更好吗?有没有更好的方法来调用SQL中未知数量的存储过程而不是循环?从存储过程调用多个存储过程 - sql while循环

让我解释一下

我要设计和实现一个供应商的邮件系统。有一家第三方公司将XML消息发送给源自发件人的收件人。我的公司可能在任何时候都是发件人或收件人。

我想出了一个使用SQL while循环来运行存储过程的设计,但是我担心它在面对大量循环时可能无法正常运行。

的基本思路是: 发件人 - >第三方(信息系统) - >接收器

当我的公司是接收器,可能会出现我的问题:

  1. 发送者发送消息至第三方公司
  2. 第三方公司发送邮件到我公司
  3. WCF服务收到来自第三方公司要求
  4. 一个存储proced URE被调用时,使消息的XML接收要被解析
  5. 这个存储过程解析XML和在XML发现消息
  6. While循环经过每一个消息,并调用存储过程来更新信息,传递的ID消息的实例。

消息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

您的问题是#6。您有一个不基于设置的存储过程。所以你需要重做这个过程.....或者像你一样做(糟糕的)循环。另一个想法是跨越C#中的多个线程/任务,并以这种方式一次发送一个线程/任务。寻找“C#平行foreach”.....但请记住,如果你的数据可能重叠,你可能会遇到种族问题。 – granadaCoder

+0

出于好奇,有没有一种方法可以以基于集合的方式在SQL中调用存储过程? – Shockwave

+0

发送到XML并粉碎它。 – granadaCoder

回答

0

我的建议是继续前进,并使用C#解析xml,并根据需要从dotnet侧调用sprocs(只要保持sql简短且甜美)。显然,我并不完全熟悉你的情况,但从我的经验来看,它很难调试sql存储过程,特别是当它们在逻辑/处理过程中很沉重,就像你正在做的那样,即使你正在使用游标/循环。在c#环境中,控制更加细化,您可以在其中放置断点,在您逐步处理时监视内存中变量的值(或者在您的情况下xml节点)的值,并捕获更广泛的错误,这些错误在从第三方接收文件。此外,尽管您可能认为sql与中网一样擅长以网络形式表现,但它不是中间件,它通常最适合在后端为您提供服务。通常在许多组织中,sql服务器在后端方面有足够的功能,而且在将来,如果你发现你的问题太多,你会发现你的sql服务器负担过重,并且它会开始在你身上出现怪异现象。最后,就性能而言,我相信这些好处大于额外的旅程时间,如果您保持sql简单并编译为存储过程,并且如果将它放在生产服务器上,则应该有足够的内存,这应该可以得到缓解。至少,如果出于性能方面的原因,我会在C#/ dotnet的偏见中取得平衡,并依靠sql server尽可能少地进行处理。

+0

谢谢 - 这就是我一直在寻找的。我更容易处理错误并从C#中分离任务,而不是在SQL中引发错误。我的计划是使用输出参数(XML或varchar类型)并处理来自C#的输出,但在思考了为什么我打算这么做后,我意识到我应该从C#中完成所有工作。 – Shockwave

0

最多1 MB的xml,我不会在存储过程中将其粉碎两次。 (你不会说在xml中有多少行)。

与逐行发送相比,您将获得更好的性能。

如果您有超过1 MB的空间,请考虑goldie-locks方法。不要一个接一个地发送它,不要将它发送到“全部”,但有一个外部c#过程将xml分解成更小的部分。例如:一个包含100,500行的文件,每次发送10,000个文件发送11个文件。

你可以玩goldie-locks方法中的数字。

..

我会验证C#你的XML,那么我会送它到SQL服务器正如我所说的“perfectXml”,然后切丝,或许到#TEMP表,然后将从那里。再说一遍,这是关键,xml应该是“完美的”,因为你没有在tsql中运行检查和if以及这个或那个语句。

行排列通过Agonizing Row是为鸟类。