【问题标题】:Could this cursor be optimized or rewritten for optimum performance?是否可以优化或重写此游标以获得最佳性能?
【发布时间】:2012-02-08 16:49:24
【问题描述】:

需要更新我们服务器上的所有数据库并在每个数据库上执行相同的逻辑。有问题的数据库都遵循一个通用的命名方案,如 CorpDB1、CorpDB2 等。我没有为每个有问题的数据库(超过 50 个)创建 SQL 代理作业,而是考虑使用游标来遍历数据库列表然后对每个执行一些动态sql。鉴于光标应该是最后手段的普遍观念;是否可以重写以获得更好的性能或使用未记录的sp_MSforeachdb stored procedure 以另一种方式编写?

DECLARE @db VARCHAR(100) --current database name
DECLARE @sql VARCHAR(1000) --t-sql used for processing on each database

DECLARE db_cursor CURSOR FAST_FORWARD FOR
    SELECT name
    FROM MASTER.dbo.sysdatabases
    WHERE name LIKE 'CorpDB%'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @db
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = 'USE ' + @db +
    ' DELETE FROM db_table --more t-sql processing'
    EXEC(@sql)
    FETCH NEXT FROM db_cursor INTO @db
END
CLOSE db_cursor
DEALLOCATE db_cursor

【问题讨论】:

  • sp_msforeachdbsp_msforeachtable 都只是游标的包装,无论如何,一些性能差异应该是最小的。
  • 嘿,想想看。我从来没有打开它们看看他们做了什么,但这并不让我感到惊讶。
  • 我不认为你会因为使用这样的游标而惹恼 SQL 之神。光标的存在不会使您的服务器停止,这是您使用它的方式和频率。在这种情况下,您将循环 50 行。我认为这比我能想到的任何替代方案都要好。
  • 对于指定 SQL Server 的 版本 总是有用的。

标签: sql-server database tsql cursor


【解决方案1】:

游标在用于处理过程代码的基于集合的问题时是不好的。我认为光标在您的场景中不一定是一个坏主意。

当需要对多个数据库运行操作(备份、完整性检查、索引维护等)时,使用游标没有问题。当然,您可以构建一个包含数据库名称的临时表并循环遍历它……但这仍然是一种程序方法。

对于您的具体情况,如果您不根据某些WHERE 子句条件删除这些表中的行,请考虑使用TRUNCATE TABLE 而不是DELETE FROM。这两个操作之间的差异解释了here。请注意,运行TRUNCATE TABLE 的用户需要对受影响的对象具有ALTER 权限。

【讨论】:

  • 这是很棒的信息,我一定会记住以备将来使用。在这个特定的例子中,delete 语句将有一个 where 子句。为了简洁起见,我把它省略了。
【解决方案2】:

这将收集一组删除语句并在一个序列中运行它们。这在性能方面不一定会更好,而只是另一种剥猫皮的方法。

DECLARE @sql NVARCHAR(MAX); -- if SQL Server 2000, use NVARCHAR(4000)

SET @sql = N'';

SELECT @sql = @sql + N';DELETE ' + name + '..db_table -- more t-sql'
  FROM master.sys.databases
  WHERE name LIKE N'CorpDB%';

SET @sql = STUFF(@sql, 1, 1, '');

EXEC sp_executesql @sql;

您可以考虑在光标内以类似的方式构建字符串,而不是为每个命令在内部运行EXEC()。如果您要继续使用游标,请使用以下声明:

DECLARE db_cursor CURSOR 
  LOCAL STATIC FORWARD_ONLY READ_ONLY
  FOR

这将具有最少的锁定并且没有不必要的 tempdb 使用。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-11-24
  • 2013-05-07
  • 2011-02-05
  • 2013-09-11
  • 2018-12-19
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多