2009-10-21 2 views
2

Я собираю задание на SQL Enterprise Manager 2000 для копирования и удаления записей в паре таблиц базы данных. Мы запускаем массовую копию с прямой массой и удаляем хранимую процедуру, но она может запускаться на миллионы строк и, следовательно, зависает на сервере. Я был заинтересован в попытке запустить службу в 100-хэш-блоках за один раз, поэтому сервер не останавливается (это живая веб-база данных). Я хочу, чтобы эта служба запускалась один раз в сутки, поэтому я поставил ее в задание агента. Есть ли способ перевести вызовы на хранимые процедуры, которые фактически выполняют копирование и удаление, а затем «поспать» между каждым вызовом, чтобы дать серверу время догнать? Я знаю, что есть команда WAITFOR, но я не уверен, что это будет удерживать процессор или позволить ему запускать другие запросы тем временем.Использование задания агента SQL для вызова процедур в цикле

Спасибо!

ответ

2

«Chunkifying» Ваши удаления - это предпочтительный способ удаления избыточных объемов данных без раздувания файлов журнала транзакций. Хорошим примером этого является сообщение BradC.

Управление такими петлями лучше всего выполнять в рамках одной хранимой процедуры. Чтобы распространить такую ​​работу со временем, я все равно буду соблюдать ее. Вставка WAITFOR в цикле поставит «паузу» между каждым набором удалений, если вы сочтете это необходимым для решения возможных проблем с параллелизмом. Используйте задание агента SQL, чтобы определить, когда запускается процедура, и если вам нужно убедиться, что она остановится на определенное время, работайте и в этом цикле.

Моя спина на этот код будет выглядеть так:

-- NOTE: This is a code sample, I have not tested it 
CREATE PROCEDURE ArchiveData 

    @StopBy DateTime 
    -- Pass in a cutoff time. If it runs this long, the procedure will stop. 
AS 

DECLARE @LastBatch int 

SET @LastBatch = 1 
-- Initialized to make sure the loop runs at least once 


WHILE @LastBatch > 0 
BEGIN 

    WAITFOR DELAY '00:00:02' 
    -- Set this to your desired delay factor 

    DELETE top 1000 -- Or however many per pass are desired 
    from SourceTable 
    -- Be sure to add a where clause if you don't want to delete everything! 

    SET @LastBatch = @@rowcount 

    IF getdate() > @StopBy 
     SET @LastBatch = 0 

END 

RETURN 0 

Хм. Перечитывая сообщение, вы должны сначала скопировать данные, прежде чем удалять их. Чтобы сделать это, я установил временную таблицу, и внутри цикла сначала обрезаем временную таблицу, а затем скопируем в первичные ключи элементов TOP N, вставьте в таблицу «архив» через соединение с временной таблицей, затем удалите исходную таблицу также через соединение с временной таблицей. (Немного сложнее, чем прямое удаление, не так ли?)

+0

Вы правы. В двух таблицах я технически «архивирую» данные, например, копируя их в другую базу данных на одном сервере, а затем удаляя существующие записи. В другой таблице я просто удаляю все записи, созданные до определенной даты. Я подумал о том, чтобы использовать временную таблицу, чтобы помочь с передачей, которую я могу закончить. Я дам ваше предложение попробовать и посмотреть, как это получается. Благодаря! – Kevin

0

WAITFOR позволит другим процессам «идти». Я использовал эту технику, чтобы остановить большой DELETE, блокирующий машину. Создайте цикл WHILE, удалите блок строк, а затем WAITFOR несколько секунд (или меньше, что бы ни было подходящим).

1

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

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

Используйте цикл, как это удалить в управляемые части:

DECLARE @i INT 
SET @i = 1 

SET ROWCOUNT 10000 

WHILE @i > 0 
BEGIN 
    BEGIN TRAN 
     DELETE TOP 1000 FROM dbo.SuperBigTable 
     WHERE RowDate < '2009-01-01' 
    COMMIT 

    SELECT @i = @@ROWCOUNT 
END 
SET ROWCOUNT 0 

Вы можете использовать подобную логику для вашей копии.

+0

Спасибо за отзыв. Имеет ли значение, был ли этот код выполнен в хранимой процедуре (и вызван из задания агента) или просто в самом задании агента? – Kevin

+0

Нет, не совсем. Просто личное предпочтение/политика компании. – BradC

Смежные вопросы