sql-server-2012 - SQL Server - While 循环与 "LOCAL STATIC READ_ONLY FORWARD_ONLY"游标

标签 sql-server-2012 cursor

我在我的应用程序中创建了许多游标,以便在每次游标单次运行中逐行操作我只选择了 500 或 1000 条记录,以便游标可以在单次运行中像 postilion 一样快地完成,换句话说,我选择了单个游标运行的记录数量有限。

为了更快地执行游标而不增加服务器负载,我使用了以下两种声明游标的方法。

声明 1: 声明 DB_CURSOR_01 CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR

声明 2: 声明 DB_CURSOR_02 CURSOR FAST_FORWARD FOR

注意:我没有使用游标的默认声明,我正在使用其他类型的游标使其工作得更快,据我所知,上面提到的声明 1 比声明 2 快,如果我错了,请纠正我。

问题: 另一种逐行操作的方法是通过“While loop using temporary table”。那么现在我的问题是,如果我使用临时表将所有游标转换为 while 循环,是否有助于提高服务器性能?

实际上,我们的 DBA 指出服务器性能受到游标的影响,如果我付出大量努力将所有这些游标转换为 while 循环,它会给我带来性能优势吗?或者我在上面提到的声明 1 中声明游标的方式将与 while 循环具有相同的性能?

最佳答案

SQL Server 中的游标非常慢。在其他 RDBMS 上,例如 Sybase,它们是可以的。

以下是如何处理它们的实用方法:

根据我“优化”旧的狡猾代码的经验,游标的主要问题是当它们基于复杂的查询时。复杂查询是指具有多个连接和/或复杂连接条件的查询。 游标所做的是,对于每次迭代,它都必须运行此连接操作,这可能比循环体内的操作花费更多的时间。

在这种情况下,将单个选择运行到临时表然后在游标中使用临时表会更有效,另一种方法是使用 STATICINSENSITIVE 关键字 ( MSDN )。要考虑的一个重要方面是并发性。通过将主游标查询的结果保存到临时表中,可以防止对游标可见的基础表的更改。

要考虑的第二个方面是游标内的选择查询。这很重要,因为每次游标迭代都会运行每个查询,因此在大表上进行选择会消耗大量资源。

我见过一些特别“狡猾”的代码,其中:

  • 使用游标的提取变量之一作为过滤器查询表以返回单个值。 - 该表应该JOIN到主游标查询。这样,该表将只查询一次并将结果保存到临时表。
  • 根据某些条件查询表以​​返回一些数据,然后再次查询以根据相同条件返回更多数据(不同的列)。 - 这两个选择应合并为一个,以便可以一次返回所有数据(所有列)。

如果您有嵌套游标(一个嵌套在另一个游标中),那将是致命的。尝试移除嵌套。

如果您有很多地方有游标,请优先修复符合上述情况之一的地方。

附言虽然循环是自己的不会拯救你。您仍然需要使用临时表并在临时表上有适当的索引。请参阅:https://dba.stackexchange.com/questions/84365/why-choose-a-top-query-and-temporary-table-instead-of-a-cursor-for-a-loop

以上链接到Aaron Bertrand讨论性能以及游标选项建议的博客。

关于sql-server-2012 - SQL Server - While 循环与 "LOCAL STATIC READ_ONLY FORWARD_ONLY"游标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45383125/

相关文章:

java - 设置 Windows 光标

java - 无法返回 Cursor 对象 - close() 从未明确称为错误

java - 不明白为什么我不能将数据追加到 ArrayList 的末尾?

sql-server-2012 - 内联表值函数中的使用选项(重新编译)

sql-server-2012 - 定义主键约束时指定现有的非聚集唯一索引

sql-server - 使用通配符时对电子邮件地址列进行全文搜索

sql - 在ms-sql中设置纪元时间戳

sql - 查询计算最有效的方式

android - sqlite android中的 "not null"子句

android - 无法使用 sqlite 查询获取过去两个月的数据