【IT168 技术】在前面的三篇文章(游标脚本性能问题详解之案例实践篇)、(游标脚本性能问题详解之游标分类特点篇 )与(游标脚本性能问题详解之解决方案篇)中我们已经对游标脚本的性能问题做了详细概述,下面让我们来一起了解一下游标的相关知识。
(一)Fast Forward Only(快速只进)游标分析
Microsoft SQL Server 实现了一种称作fast forward only游标的性能优化。http://msdn.microsoft.com/zh-cn/library/ms187502.aspx
当遇到下面情形时,Fast Forward-only游标会隐式转换为其他类型
1. 当SELECT语句连接包含trigger table(INSERTED/DELETED)的一个或多个表,游标被转换成static类型。
2. 当SELECT语句查阅text、ntext或image列,如果SQL Server OLE DB访问接口或使用了SQL Server ODBC驱动器,游标被转换成dynamic类型。
3. 当Fast Forward-only游标不是只读的,它会被转换成dynamic游标。动态游标是可以用来update当前滚动到的数据行并将更新回写到table中的。
4. 当SELECT语句是一个查阅了链接服务器中一个或多个远程表进行分部查询,游标被转换成keyset-driven类型。
5. 如果SELECT语句查阅text、ntext或image列以及TOP语句,游标被转换成keyset-driven类型。
(二)几种游标的使用规则:
另外,我们这里列出了几条游标使用规则可供参考:
1. 如果应用程序中,只能使用服务器端游标(所有在SQL Server上定义的游标都是服务器端游标,如果应用程序在客户端使用游标,在SQL Server端是不会看到有游标打开的),尽量选择使用FORWARD-ONLY、FAST-FORWARD、READ-ONLY游标。当处理单向只读数据时,使用FAST_FORWARD选项而不是FORWARD_ONLY,因为它可以提供一些内部的性能优化。这种类型的所游标产生的SQL Server整体开销是最少的。如果您无法使用FAST_FORWARD游标,可以按序尝试使用下面的游标,找到适合您需求的游标。按照他们的性能特征列出,从最快到最慢为:dynamic,static,keyset。
2. 除非没有其他选择,避免使用static/insensitive和keyset游标,这是因为他们会在TEMPDB中创建临时表,这会增加整体开销导致内存抢夺问题。
3. 使用游标会减少并行而导致不必要的锁和阻塞的发生。要避免这种情况,可以适当地使用READ_ONLY游标选项;或者在你需要进行更新时,使用OPTIMISTIC游标选项来减少锁的产生。避免使用SCROLL_LOCKS游标选项,因为它会减少并行。
4. 从应用程序的角度尽快的加载并且滚动游标到最后一行。这会释放在创建游标时随之创建的共享锁,从而释放SQL Server资源。
5. 如果你的应用程序需要手动滚动记录并进行更新而必须使用游标,请避免使用客户端游标,除非返回的行数很少或数据是静态的。如果行数很大,或者数据不是静态的,可以考虑使用服务器端的keyset游标。由于客户端和服务器端网络拥挤的减少,性能问题很可能会出现。为了优化性能,可能需要在实际情况下对两种游标类型都进行尝试,决定哪种更适合需要应用的系统。
6. 如果游标需要执行JOIN操作,keyset和static游标通常比dynamic游标快。
(三)深入了解Fast_forward游标
1. 既然已经有了read_only forward_only游标,fast_forward游标岂不是是多余的?为什么还需要它们?
fast_forward的确是”多余”的。read_only forward_only游标确实适用于很多应用,但是在有些应用的查询计划中却不理想。Read_only forward_only游标是动态游标,动态游标一般使用的是动态计划。问题在于��有些情况下即使最好的动态计划也远不如静态计划。因此我们引入了Fast_forward游标来使用了一种更平衡的方式,当静态计划更适合时它会选择静态计划。
2. 什么时候用fast_forward,什么时候用read_only forward_only?
综合来说,fast_forward游标更好一点。但是,在做最后决定之前应该先对您的应用进行性能测试。这是因为,使用动态或者静态计划的决定方式是完全不同的(看下面的解释)。不论使用哪种计划方式或哪种游标模式,索引调优(index tuning)或计划提示(plan hint)都会是游标优化的一个重要部分。