Pergunta

Estou juntando um trabalho no SQL Enterprise Manager 2000 para copiar e excluir registros em um banco de dados tabelas casal. Nós funcionamos uma cópia em massa se em linha reta e apagar procedimento armazenado, mas poderia ser executá-lo em milhões de linhas, e, portanto, paira o servidor. Eu estava interessado em tentar executar o serviço em pedaços ficha 100-ish de cada vez, para que o servidor não ficar paralisada (este é um banco de dados web ao vivo). Quero que este serviço para ser executado uma vez por noite, que é por isso que eu colocá-lo em um trabalho de agente. Existe alguma maneira para repetir as chamadas para os procedimentos armazenados que realmente fazem o copiar e excluir, em seguida, "dormir" entre cada chamada para dar tempo ao servidor para recuperar o atraso? Eu sei que há o comando WAITFOR, mas não estou certo se isso vai segurar o processador ou deixá-lo correr outras consultas no mesmo período.

Obrigado!

Foi útil?

Solução

"Chunkifying" suas exclusões é a forma preferida para eliminar quantidades excessivas de dados sem inchaço dos arquivos de log de transações. O post de BradC é um exemplo razoável desta.

A gestão de tais laços é o melhor feito dentro de um único procedimento armazenado. Para difundir esse tipo de trabalho ao longo do tempo, eu ainda mantê-lo no procedimento. Inserindo um WAITFOR no circuito vai colocar uma "pausa" entre cada conjunto de exclusões, se você considerar que necessário para lidar com possíveis problemas de concorrência. Use um trabalho do SQL Agent para determinar quando o início procedimento -. E se você precisa ter certeza de que ele pare por um determinado período de tempo, trabalho que para o loop assim

O meu giro sobre este código seria:

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

Hmm. Relendo você postar implica que você deseja copiar os dados em algum lugar antes de excluí-lo. Para fazer isso, eu criar uma tabela temporária, e dentro do loop primeira truncar a tabela temporária, em seguida, copiar nas chaves primárias do TOP N itens, inserção na tabela de "arquivo" através de um Registra-se para a tabela temporária, em seguida, excluir a tabela de origem também através de uma junção para a tabela temporária. (Apenas um pouco mais complexo do que uma exclusão em linha reta, não é?)

Outras dicas

Não se preocupe com espera entre loops, servidor SQL deve lidar com a disputa entre o seu trabalho de manutenção ea atividade regular no servidor.

O que realmente faz com que o problema nesses tipos de situações é que todo o processo de exclusão acontece tudo de uma vez, dentro de uma única transação. Este explode o log do banco de dados, e pode causar os tipos de problemas, parece que você está enfrentando.

Use um loop como este para apagar em partes gerenciáveis:

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

Você pode usar a lógica semelhante para a sua cópia.

WAITFOR vai deixar outros processos 'ter um go'. Eu usei esta técnica para parar grandes de APAGAR travando a máquina. Criar um loop while, apagar um bloco de linhas, e depois waitFor alguns segundos (ou menos, o que for apropriado).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top