SQL Archive Script - PullRequest
       8

SQL Archive Script

8 голосов
/ 22 октября 2009

Я пытаюсь архивировать записи из таблицы в базе данных в идентичную таблицу в архивной базе данных. Мне нужно иметь возможность сделать вставку для всех записей с датой, превышающей три года назад, а затем удалить эти строки. Тем не менее, эта таблица содержит миллионы записей, которые являются действующими, поэтому я хочу запускать это в цикле примерно от 100 до 1000 фрагментов за раз. Пока что моя хранимая процедура выполняет весь оператор вставки, затем оператор удаления (в транзакции) с тем же условием WHERE, что и оператор вставки. Мой цикл WHILE ищет самую старую дату в таблице, чтобы определить, когда цикл завершен. Часть этого кажется довольно неэффективной. Есть ли способ, которым я могу сделать вставку и удаление на порции записей без необходимости искать их дважды в одном и том же цикле выполнения? Есть ли лучший способ определить, когда инструкция WHILE завершена? Запуск MS SQL Server 2000.

Это моя текущая процедура (ISAdminDB - основная БД, ISArchive - архивная БД):

    WHILE ( (SELECT MIN( [MyTable].[DateTime]) FROM  [ISAdminDB].[dbo].[MyTable]) < DATEADD(d, -(3 * 365), GetDate()))
BEGIN

INSERT INTO [ISArchive].[dbo].[MyTable] 
(<Fields>)
SELECT TOP 1000 (<Fields>)
FROM  [ISAdminDB].[dbo].[MyTable]
WHERE 
   [MyTable].[DateTime] < DATEADD(d, -(3 * 365), GetDate())
AND  UniqueID in (SELECT TOP 1000 UniqueID  FROM  [ISAdminDB].[dbo].[MyTable] ORDER BY [MyTable].[DateTime] ASC )

BEGIN TRAN
DELETE FROM  [ISAdminDB].[dbo].[MyTable]
WHERE   [MyTable].[DateTime] < DATEADD(d, -(3 * 365), GetDate()) 
AND  (UniqueID in (SELECT TOP 1000 UniqueID FROM  [ISAdminDB].[dbo].[MyTable] ORDER BY [MyTable].[DateTime] ASC))
COMMIT

END

1 Ответ

6 голосов
/ 22 октября 2009

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

Так что теперь у нас есть:

DECLARE @NextIDs TABLE(UniqueID int primary key)
DECLARE @ThreeYearsAgo datetime
SELECT @ThreeYearsAgo = DATEADD(d, -(3 * 365), GetDate())

WHILE EXISTS(SELECT 1 FROM [ISAdminDB].[dbo].[MyTable] WHERE [MyTable].[DateTime] < @ThreeYearsAgo)
BEGIN 
    BEGIN TRAN 

    INSERT INTO @NextIDs(UniqueID)
        SELECT TOP 1000 UniqueID FROM [ISAdminDB].[dbo].[MyTable] WHERE [MyTable].[DateTime] < @ThreeYearsAgo

    INSERT INTO [ISArchive].[dbo].[MyTable] (<Fields>) 
        SELECT (<Fields>) 
        FROM  [ISAdminDB].[dbo].[MyTable] AS a
        INNER JOIN @NextIDs AS b ON a.UniqueID = b.UniqueID

    DELETE [ISAdminDB].[dbo].[MyTable]
    FROM  [ISAdminDB].[dbo].[MyTable] 
    INNER JOIN @NextIDs AS b ON a.UniqueID = b.UniqueID 

    DELETE FROM @NextIDs

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