11

在尝试帮助一个应用程序开发团队解决 SQL 2000 服务器上的性能问题(来自不同应用程序服务器上的一堆 Java 应用程序)的过程中,我运行了 SQL 跟踪并发现对数据库的所有调用都充满了 API服务器游标语句(sp_cursorprepexec、sp_cursorfetch、sp_cursorclose)。

看起来他们正在指定一些强制使用服务器端游标的连接字符串属性,一次只检索 128 行数据:(来自http://msdn.microsoft.com/en-us/library/Aa172588

当 API 游标属性或属性设置为默认值以外的任何值时,SQL Server 的 OLE DB 提供程序和 SQL Server ODBC 驱动程序使用 API 服务器游标而不是默认结果集。每次调用获取行的 API 函数都会生成到服务器的往返行程,以从 API 服务器游标中获取行。

更新:有问题的连接字符串是一个 JDBC 连接字符串参数,selectMethod=cursor(它启用我们上面讨论的服务器端游标)与替代selectMethod=direct. 他们一直将selectMethod=cursor其用作所有应用程序的标准连接字符串。

从我的 DBA 的角度来看,这很烦人(它用无用的垃圾使跟踪变得混乱),并且(我推测)会导致许多额外的应用程序到 SQL 服务器往返,从而降低整体性能。

他们显然确实测试了更改(只是大约 60 个不同的应用程序连接之一),selectMethod=direct但遇到了一些问题(我没有详细信息),并且担心应用程序会中断。

所以,我的问题是:

  • selectMethod=cursor正如我试图争论的那样,可以使用较低的应用程序性能吗?(通过增加已经有非常高的查询/秒的 SQL 服务器上所需的往返次数)
  • selectMethod=JDBC 连接上的应用程序透明设置吗?如果我们改变它,这会破坏他们的应用程序吗?
  • 更一般地说,什么时候应该使用cursorvs direct

交叉发布到 SF

编辑:收到实际的技术细节,需要对标题、问题和标签进行重大编辑。

编辑:增加赏金。还为 SF 问题添加了赏金(此问题侧重于应用程序行为,SF 问题侧重于 SQL 性能。)谢谢!

4

2 回答 2

13

简要地,

  1. selectMethod=cursor
    • 理论上需要比服务器端更多的资源selectMethod=direct
    • 一次最多只能将批量大小的记录加载到客户端内存中,从而导致更可预测的客户端内存占用
  2. selectMethod=direct
    • 理论上需要的服务器端资源少于selectMethod=cursor
    • 将整个结果集读入客户端内存(除非驱动程序本身支持异步结果集检索),然后客户端应用程序才能对其进行迭代;这可以通过两种方式降低性能
      1. 如果客户端应用程序的编写方式是在仅遍历结果集的一小部分后停止处理,则会降低大型结果集的性能(direct它已经支付了检索数据的成本,它将基本上丢弃;cursor浪费是限于最多批量大小- 1 行 - 提前终止条件可能应该在 SQL 中重新编码,例如 asSELECT TOP或窗口函数)
      2. 由于潜在的垃圾收集和/或与内存占用增加相关的内存不足问题,导致大型结果集的性能下降

总之,

  • 可以使用selectMethod=cursor较低的应用程序性能吗?-- 出于不同的原因,任何一种方法都会降低性能。超过一定的结果集大小,cursor可能仍然是可取的。请参阅下文了解何时使用其中一种
  • selectMethod=JDBC 连接上的应用程序透明设置吗?-- 它是透明的,但如果内存使用量增长到足以占用他们的客户端系统(以及相应地,你的服务器)或完全崩溃客户端,它仍然会破坏他们的应用程序
  • 更一般地说,什么时候应该使用cursorvs direct-- 我个人cursor在处理可能很大或无界的结果集时使用。然后,给定足够大的批处理大小,来分摊往返开销,并且我的客户端内存占用是可预测的。direct当我期望的结果集的大小已知低于我使用的任何批量大小时,cursor或者以某种方式绑定,或者当内存不是问题时,我会使用。
于 2010-09-14T04:08:03.907 回答
1

使用会selectMethod=cursor阻止 SQL Server 使用Parallel Query Processing,这可能会对性能产生很大影响,例如在以下情况下:

  • 你有很多 CPU 内核(谁没有?)
  • 你已经通过分区表优化了你的数据库
  • 您正在运行大量聚合查询(sum(),count()等)

最后,微软声明如下:

( selectMethod=direct) 在应用程序处理所有行时提供最快的性能。

您绝对应该尝试看看设置 selectMethod=direct 是否对您有所帮助。

于 2013-07-31T16:19:01.457 回答