这并不是说我在执行包含在存储过程中的游标时遇到了问题。但我想找到更有效的方法来实现同样的目标。
在这里。
存储过程: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
包含输入string
存储过程的以下usp_pushRawDataAndProcess
。现在这将划分整个字符串并在某些表上执行INSERT,UPDATE,DELETE
之类的操作。
我们不能在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
答案 0 :(得分:3)
与其他关系数据库一样,SQL Server被设计为并且相当擅长处理数据集。
数据库不擅长程序代码,其中所有优化机会都会从查询处理引擎中隐藏。
使用RawStatusFeed
存储一些专有请求字符串,然后逐个处理这些字符串的列表,对于数据库代码来说将是无效的。这可能会使客户端的插入速度非常快,这可能非常重要,但需要付出代价。
如果在插入时断开请求字符串,或者更好,在通过专门的SP调用插入之前,则可以在一些中间关系模型中存储所需的更改,而不是字符串列表。然后,每隔一段时间,您就可以通过一次调用存储过程一次处理所有更改。不可否认,该存储过程可能包含多个查询语句。但是,通过正确的索引和统计信息,查询处理引擎将能够为此新存储过程制定有效的执行计划。
应如何实现此目标的具体细节取决于RawStatusFeed
表的详细信息和usp_pushRawDataAndProcess
的实现。虽然这看起来像是重写,但我认为DeviceCode
列并不复杂。
所以,简短的答案当然是肯定的,但是,我需要知道usp_pushRawDataAndProcess
的详细内容。
usp_pushRawDataAndProcess
SP的签名充当瓶颈。
如果你不能改变usp_pushRawDataAndProcess
并且不会创建一个基于集合的替代方案,那么你就会被瓶颈困住。
所以,不是取下瓶颈,你可以采取另一种方法。为什么不制作更多并发的瓶颈实例来提供数据。
如果您使用的是SQL Server 2005或更高版本,则可以使用某些CLR并行执行多个usp_pushRawDataAndProcess
实例。
Here is a link到我之前用过类似事情的项目。
答案 1 :(得分:3)
由于性能缓慢,我一直不喜欢游标。但是,我发现我并没有完全理解不同类型的游标,在某些情况下,游标是一个可行的解决方案。
如果您遇到的业务问题只能通过一次处理一行来解决,那么光标就是合适的。
因此,要使用光标提高性能,请更改正在使用的光标类型。我不知道的是,如果你没有指定你声明的光标类型,默认情况下会得到动态乐观类型,这是性能最慢的类型,因为它在引擎盖下做了很多工作。但是,通过将游标声明为不同的类型,例如静态游标,它具有非常好的性能。
有关更全面的解释,请参阅这些文章:
The Truth About Cursors: Part I
The Truth About Cursors: Part II
The Truth About Cursors: Part III
我认为对游标最大的反对意见是性能,但是,在基于集合的方法中没有布置任务可能排在第二位。第三是任务的可读性和布局,因为它们通常没有很多有用的评论。
我发现光标的最佳替代方法是重新设计逻辑以采用基于集合的方法。
SQL Server经过优化,可以运行基于集合的方法。您编写查询以返回结果数据集,例如表上的连接,但SQL Server执行引擎确定要使用的连接:合并连接,嵌套循环连接或散列连接。 SQL Server根据参与列中的参与列,数据量,索引结构和值集确定最佳连接算法。因此,它通常是性能优于程序游标方法的最佳方法。
这是关于Cursors and how to avoid them.的文章。它还讨论了游标的替代方案。
答案 2 :(得分:0)
在SQL服务器中为CURSOR进行Alernates
1.While loop
2.Recursive CTE
答案 3 :(得分:0)
在SQL Server中对CURSOR的别名
1。使用临时表。创建任何列ID作为标识列。
2。使用while循环执行操作。