2009-10-22 3 views
8

Próbuję archiwizować rekordy z tabeli w bazie danych do identycznej tabeli w bazie danych archiwum. Muszę umieć wstawić wszystkie rekordy z datą większą niż trzy lata temu, a następnie usunąć te wiersze. Jednak ta tabela zawiera miliony rekordów na żywo, więc chcę uruchomić to w pętli z grubsza od 100 do 1000 porcji na raz. Do tej pory moja procedura przechowywana wykonuje całą instrukcję insert, następnie instrukcję delete (w transakcji) z zasadniczo tą samą klauzulą ​​WHERE, co instrukcja insert. Moja pętla WHILE szuka najstarszej daty w tabeli, aby określić, kiedy pętla zostanie ukończona. Niektóre z nich wydają się dość nieskuteczne. Czy istnieje sposób, w jaki można wstawić i usunąć w kawałku rekordów bez konieczności wyszukiwania dwa razy w tym samym wykonaniu pętli? Czy istnieje lepszy sposób określenia, kiedy instrukcja WHILE została zakończona? Uruchamianie MS SQL Server 2000.Archiwum SQL Skrypt

To moja obecna procedura (ISAdminDB jest głównym DB ISArchive jest DB archiwum):

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 
+0

Które RDBMS? SQL Server, MySQL, coś jeszcze? – MartW

+0

Przeprosiny, MS SQL Server 2000. – Kevin

+0

Zgaduję, że SQL Server – MartW

Odpowiedz

6

Najpierw usuwasz zapisy wcześniej niż dany termin 3 Lata temu. Nie obchodzi cię kolejność, w jakiej zostały usunięte, po prostu musisz je usuwać, dopóki nie pozostanie żadna kolejność. Możesz także przyspieszyć działanie, korzystając z tabeli tymczasowej do przechowywania identyfikatorów oraz zapisując datę wyłączenia w zmiennej i powtarzając ją wielokrotnie.

Więc teraz mamy:

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 
+0

Dzięki! Doceniam twój wkład. Wydaje się działać. – Kevin