2012-02-13 12 views
5

La empresa para la que trabajo tiene algunas tablas enormes de registro/diario que se escriben cada 10 segundos más o menos con transacciones. Me gustaría copiar muchos de los datos en esta tabla y eliminarlos de esa tabla porque aproximadamente el 75% de los datos anteriores podrían colocarse en una tabla de archivo o algo así, pero si lo hago mal y la tabla se bloquea hasta sería un desastre.copia de datos de una gran tabla de producción

En una pregunta anterior a un chico se le ocurrió algo así, me gustaría saber que esto no lo arruinaría todo, ¿es la pista de nolock suficiente para mantenerme a salvo y todas las escrituras funcionan bien? Si no, ¿qué debería hacer?

set identity_insert newtable on 
DECLARE @StartID bigint, @LastID bigint, @EndID bigint 
select @StartID = max(id)+1 
from newtable 

select @LastID = max(ID) 
from oldtable 

while @StartID < @LastID 
begin 
set @EndID = @StartID + 1000000 

insert into newtable (FIELDS,GO,HERE) 
select FIELDS,GO,HERE from oldtable (NOLOCK) 
where id BETWEEN @StartID AND @EndId 

set @StartID = @EndID + 1 
end 
set identity_insert newtable off 
go 
+1

Esto es genial, excepto ¿cuál es su plan para ELIMINAR los registros anteriores? No es realmente una forma de hacer eso sin que ocurra algún tipo de bloqueo. – JNK

+0

Sí, aclaré un poco la pregunta, entonces, ¿cuál es la mejor manera de eliminar los registros anteriores sin interferir con las operaciones normales de DB? –

Respuesta

3

La extrema precaución en la generación de su lista probablemente esté por la borda, pero querrá ejecutar una eliminación por lotes.

Para el INSERT, probablemente no necesite el bucle WHILE. Para el DELETE, sin embargo, me gustaría utilizar algo como esto (ajustar el tamaño del lote a sus necesidades):

WHILE 1=1 
BEGIN 
    DELETE TOP (10000) o 
    FROM OldTable o 
    INNER JOIN NewTable N 
     ON o.id = n.id 
    IF @@ROWCOUNT < 10000 BREAK; 
END 

Esto hará DELETE registros 10k a la vez, siempre y cuando hay registros que desea eliminar.

+0

He hecho algo similar en el pasado con una tabla grande, archivando y eliminando registros en lotes . Básicamente se parecía a tu código pero con un "comenzar tran" y un "commit tran" dentro del ciclo while. Luego hice una copia de seguridad, trunqué y reduje el registro. –

+0

Si le preocupa la disputa, no haría una transacción ya que eso bloquearía la mesa :) – JNK

+0

Gracias JNK, ¿entonces recomendaría que primero haga la copia y luego la elimine? ¿Algo más de lo que deba preocuparme? Lo siento, estoy súper paranoico, pero creo que parece que funcionaría. –

0

Una opción es dividir la tabla por hora (suponiendo que tiene una columna en la tabla DATETIME que por defecto es GETDATE() en cada inserto). Tener las particiones le permite realizar tareas de mantenimiento (colocar, copiar, etc.) en las particiones más antiguas sin afectar la actual.

+1

Le preocupa cerrar la mesa lo suficiente para seleccionarla y está sugiriendo agregar un esquema de partición. Estoy bastante seguro de que también causará algunos bloqueos ... – JNK

+0

@JNK sí, pero eso podría ser parte de un futuro tiempo de inactividad planeado –

Cuestiones relacionadas