Может ли этот курсор быть оптимизирован или переписан для оптимальной производительности? - PullRequest
3 голосов
/ 08 февраля 2012

Необходимо обновить все наши базы данных на нашем сервере и выполнить одинаковую логику для каждой из них.Все рассматриваемые базы данных следуют общей схеме именования, такой как CorpDB1, CorpDB2 и т. Д. Вместо создания задания агента SQL для каждой из рассматриваемых баз данных (более 50), я подумал об использовании курсора для перебора списка баз данных.а затем выполнить некоторые динамические SQL на каждом.В свете распространенного мнения, что курсоры должны быть последним средством;Можно ли это переписать для повышения производительности или написать другим способом, возможно, с использованием недокументированной хранимой процедуры sp_MSforeachdb ?

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

Ответы [ 2 ]

5 голосов
/ 08 февраля 2012

Курсоры плохи, когда они используются для решения основанной на множестве проблемы с процедурным кодом.Я не думаю, что курсор - это плохая идея в вашем сценарии.

Когда нужно запускать операции над несколькими базами данных (резервное копирование, проверка целостности, обслуживание индекса и т. Д.), Нет проблем с использованиемкурсор.Конечно, вы могли бы создать временную таблицу, которая содержит имена баз данных и проходить через нее ... но это все еще процедурный подход.

Для вашего конкретного случая, если вы не удаляете строки в этих таблицах на основе некоторыхWHERE критерий предложения, рассмотрите возможность использования TRUNCATE TABLE вместо DELETE FROM.Различия между этими двумя операциями объясняются здесь .Обратите внимание, что пользователю, работающему с TRUNCATE TABLE, потребуется разрешение ALTER для затронутых объектов.

2 голосов
/ 08 февраля 2012

Это соберет набор операторов удаления и выполнит их все в одной последовательности. Это не обязательно будет лучше с точки зрения производительности, но это просто еще один способ снять шкуру с кошки.

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...