5

这并不是说我在执行包含在存储过程中的游标时遇到问题。但我想找到更有效的方法来实现同样的目标。

就这样吧。

存储过程:(RawFeed.sql每 5 分钟运行一次)

Set @GetATM = Cursor For
        Select DeviceCode,ReceivedOn
        From RawStatusFeed
        Where CRWR=2 AND Processed=0
        Order By ReceivedOn Desc
    Open @GetATM
    Fetch Next
    From @GetATM Into @ATM,@ReceivedOn
    While @@FETCH_STATUS = 0
        Begin
            Set @RawFeed=@ATM+' '+Convert(VarChar,@ReceivedOn,121)+' '+'002307'+' '+@ATM+' : Card Reader/Writer - FAULTY '
            Exec usp_pushRawDataAndProcess 1,@RawFeed
            Fetch Next
            From @GetATM Into @ATM,@ReceivedOn
        End
Set @GetATM = Cursor For
        Select DeviceCode,ReceivedOn
        From RawStatusFeed
        Where CRWR=0 AND Processed=0
        Order By ReceivedOn Desc
    Open @GetATM
    Fetch Next
    From @GetATM Into @ATM,@ReceivedOn
    While @@FETCH_STATUS = 0
        Begin
            Set @RawFeed=@ATM+' '+Convert(Varchar,@ReceivedOn,121)+' '+'002222'+' '+@ATM+' : Card Reader/Writer - OK '
            Exec usp_pushRawDataAndProcess 1,@RawFeed
            Fetch Next
            From @GetATM Into @ATM,@ReceivedOn
        End

同样,我还有 10 条SET语句在条件参数和包含在变量中WHERE的字符串上有所不同。@RawFeed

对于我得到的每一行,我在该特定行上执行另一个存储过程。

我的问题是

有没有更好的方法可以在不使用游标的情况下实现相同的目标?

变量@RawFeed包含以下stringusp_pushRawDataAndProcess存储过程的输入。现在这将分割整个字符串并INSERT,UPDATE,DELETE在某些表上执行一些操作。

我们不能处理超过 1 个字符串usp_pushRawDataAndProcess

NMAAO226 2012-09-22 16:10:06.123 002073 NMAAO226 : Journal Printer - OK 
WMUAO485 2012-09-22 16:10:06.123 002222 WMUAO485 : Card Reader/Writer - OK 
4

4 回答 4

3

SQL Server 与其他关系数据库一样,旨在并且非常擅长处理数据集。

数据库不擅长程序代码,因为查询处理引擎掩盖了所有优化机会。

使用RawStatusFeed存储一些专有请求字符串,然后一一处理这些列表,对于数据库代码将是低效的。这可能会使客户端的插入速度非常快,这可能非常重要,但这是有代价的。

如果您在插入时分解请求字符串,或者更好的是,在插入之前通过专门的 SP 调用,那么您可以将所需的更改存储在一些中间关系模型中,而不是字符串列表中。然后,每隔一段时间,您就可以通过一次调用存储过程来一次处理所有更改。诚然,该存储过程包含多个查询语句可能是有意义的。但是,使用正确的索引和统计信息,查询处理引擎将能够为这个新的存储过程制定有效的执行计划。

如何实现这一点的具体细节取决于RawStatusFeed表格的具体细节和usp_pushRawDataAndProcess. 虽然这看起来像是重写,但我不认为DeviceCode专栏有那么复杂。


所以,简短的回答肯定是肯定的,但是,我需要知道具体是做什么usp_pushRawDataAndProcess的。

SP的签名usp_pushRawDataAndProcess就像一个瓶颈。


如果您无法改变usp_pushRawDataAndProcess并且不会创建基于集合的替代方案,那么您将陷入瓶颈。

因此,您可以采取另一种策略,而不是消除瓶颈。为什么不创建更多并发瓶颈实例来提供数据。

如果您使用的是 SQL Server 2005 或更高版本,您可以使用一些 CLR 来usp_pushRawDataAndProcess并行执行多个实例。

这是我以前用来做类似事情的项目的链接。

于 2012-09-26T11:38:26.763 回答
3

我一直不喜欢游标,因为它们的性能很慢。但是,我发现我并不完全了解不同类型的游标,并且在某些情况下,游标是一种可行的解决方案。

当您有一个只能通过一次处理一行来解决的业务问题时,游标是合适的。

因此,要提高游标的性能,请更改您正在使用的游标类型。我不知道的是,如果您不指定要声明的游标类型,则默认情况下会获得 Dynamic Optimistic 类型,这是性能最慢的类型,因为它在后台做了很多工作. 但是,通过将游标声明为不同的类型,比如静态游标,它具有非常好的性能。

请参阅这些文章以获得更全面的解释:

关于光标的真相:第一部分

关于光标的真相:第二部分

关于光标的真相:第三部分

我认为对游标的最大缺点是性能,但是,如果不在基于集合的方法中布置任务可能会排在第二位。第三是任务的可读性和布局,因为它们通常没有很多有用的评论。

我发现的光标的最佳替代方法是重新设计逻辑以采用基于集合的方法。

SQL Server 已针对运行基于集合的方法进行了优化。您编写查询以返回数据的结果集,例如表连接,但 SQL Server 执行引擎确定要使用的连接:合并连接、嵌套循环连接或散列连接。SQL Server 根据参与列、数据量、索引结构和参与列中的值集确定可能的最佳连接算法。因此,它通常是程序游标方法的最佳性能方法。

这是一篇关于游标以及如何避免它们的文章。 它还讨论了游标的替代方案。

于 2013-08-21T14:34:09.933 回答
0

SQL Server 中 CURSOR 的警报

1.While loop
2.Recursive CTE
于 2012-09-26T11:11:48.123 回答
0

SQL 服务器中 CURSOR 的警报
1.使用临时表。创建任何列 ID 作为标识列。
2.使用while循环来执行操作。

于 2018-11-27T12:21:08.737 回答