tablas - Cómo borrar 8,500,000 registros de una tabla en el servidor sql
eliminar varios registros sql (6)
Puedes hacerlo en pedazos. Por ejemplo, cada 10 segundos ejecuta:
delete from activities where activityid in
(select top 1000 activityid from activities where unt_uid is null)
Obviamente, defina el recuento de filas (seleccioné arbitrariamente 1000) y el intervalo (seleccioné 10 segundos), lo que tiene más sentido para su aplicación.
eliminar actividades donde unt_uid es nulo
sería la forma más rápida, pero nadie puede acceder a la base de datos / tabla hasta que esta declaración haya finalizado, por lo que este es un no-go.
Definí un cursor para realizar esta tarea durante el tiempo de trabajo, pero de todos modos el impacto para la productividad es grande. Entonces, ¿cómo eliminar estos registros para garantizar el uso normal de esta base de datos?
Es un servidor SQL-2005 en un Win2003 de 32 bits. La segunda pregunta es: ¿Cuánto tiempo estimaría usted para realizar este trabajo (6 horas o 60 horas)? (Sí, sé que eso depende de la carga, pero supongamos que se trata de un entorno de pequeñas empresas)
Quien pueda acceder a la tabla dependerá del modo de aislamiento de su transacción, supongo.
Sin embargo, tiene usted razón: muchas eliminaciones son malas, especialmente si su cláusula where significa que no puede usar un índice, lo que significa que la base de datos probablemente no podrá bloquear solo las filas que necesita eliminar, por lo que finalizará tomando un gran candado en toda la mesa.
Mi mejor recomendación sería rediseñar su aplicación para que no tenga que eliminar estas filas, o posiblemente ninguna fila.
Puede hacer esto dividiendo la tabla de forma tal que simplemente pueda soltar particiones o utilizar la receta "copiar las filas que desea conservar y luego soltar la mesa" sugerida por otros.
Quizás en lugar de eliminar los registros de su tabla, podría crear una nueva tabla idéntica, insertar los registros que desea conservar y luego cambiar el nombre de las tablas para que la nueva reemplace a la anterior. Esto aún tomaría algo de tiempo, pero el tiempo de inactividad en su sitio sería bastante mínimo (justo cuando se intercambian las tablas)
En un entorno de pequeñas empresas, parece extraño que tenga que eliminar 500,000 filas en el comportamiento operativo estándar sin afectar a otros usuarios. Por lo general, para eliminar ese tamaño grande, estamos creando una nueva tabla y usando TRUNCATE / INSERT o sp_rename para sobrescribir el antiguo.
Habiendo dicho eso, en un caso especial, uno de mis procesos mensuales puede eliminar regularmente 200m filas en lotes de alrededor de 3m a la vez si detecta que necesita volver a ejecutar el proceso que generó esas 200m filas. Pero este es un proceso de un solo usuario en una base de datos de data warehouse dedicada, y no lo llamaría un escenario de pequeñas empresas.
En segundo lugar las respuestas que recomiendan buscar enfoques alternativos a su diseño.
Utilizaría la técnica de "eliminar mordiscos". Desde http://sqladvice.com/blogs/repeatableread/archive/2005/09/20/12795.aspx :
DECLARE @target int
SET @target = 2000
DECLARE @count int
SET @count = 2000
WHILE @count = 2000 BEGIN
DELETE FROM myBigTable
WHERE targetID IN
(SELECT TOP (@target) targetID
FROM myBigTable WITH(NOLOCK)
WHERE something = somethingElse)
SELECT @count = @@ROWCOUNT
WAITFOR DELAY ''000:00:00.200''
END
Lo he usado exactamente para este tipo de escenario. El WAITFOR
es importante de mantener, permite que otras consultas hagan su trabajo entre las eliminaciones.
Crearía una tarea para esto y programaría que se ejecute durante las horas pico. Pero no le sugiero que lo elimine en la tabla que está utilizando. Mueva las filas que desea mantener a la nueva tabla y suelte totalmente la tabla actual con muchas filas que desea eliminar.