2008-11-12 11 views
6

Cada noche tengo que recortar una tabla para que solo contenga los últimos 20,000 registros. Podría usar una subconsulta:¿Cómo borrar todos los 20,000 registros menos en MS SQL 2005?

delete from table WHERE id NOT IN (select TOP 20000 ID from table ORDER BY date_added DESC) 

Pero eso parece ineficiente, especialmente si luego decidimos mantener 50,000 registros. Estoy usando SQL 2005, y pensé que podría usar ROW_NUMBER() OVER de alguna manera para hacerlo? Pídalos y elimine todos los que tengan un ROW_NUMBER mayor a 20,000? Pero no pude hacer que funcione. ¿Es la subconsulta mi mejor apuesta o hay una mejor manera?

Respuesta

7

Si solo parece ineficaz, me aseguraría de que sea ineficaz antes de que empiece a ladrar en el árbol equivocado.

Mide el tiempo, el uso de la CPU, las E/S de disco, etc. para ver qué tan bien funciona. Creo que encontrarás que funciona mejor de lo que piensas.

+0

Tiene usted razón, su única tomando 3 segundos para limpiar la mesa con alrededor de 50.000 registros en ella. Pensé que las cláusulas IN() eran muy ineficientes, pero quizás eso sea justo cuando realmente pasas una lista textual de ID. Gracias por la ayuda. –

+0

Sí, una cláusula IN() con 20,000 ID separados por comas probablemente sería bastante ineficiente. Sin embargo, apostaría que todavía se ejecutaría en algo así como 10-15 segundos. – MusiGenesis

+0

Eso es si aceptó incluso analizar una cadena tan larga, por supuesto. – MusiGenesis

0

Seguramente este es un buen ejemplo para completar un procedimiento y usar dos sentencias sql: la primera para seleccionar la última ID y restar 20,000, luego la segunda para eliminar todas las filas con identificaciones inferiores a esta.

Sin embargo, parece que va a terminar con una gran fragmentación yendo con este enfoque y ese podría ser un buen argumento para crear una nueva tabla, insertando los últimos 20,000 registros en ella , eliminando el antiguo y renombrando el nuevo. Incluso podría valer la pena colocar la tabla en una base de datos diferente y crear una vista desde su base de datos principal para facilitar el acceso. Yo generalmente tiendo a hacer esto con tablas usadas para carga de datos y auditoría.

Es muy difícil de decir sin conocer el volumen de datos y el comportamiento real, pero bien podría ser que a nivel mundial sus ineficiencias surgirán más de esto que el método de eliminación que utiliza. Si solo está recolectando un millar de registros o menos por día, entonces es probable que la eliminación esté bien combinada con la ejecución de un plan de mantenimiento de optimización de datos, pero más y estaría buscando un enfoque más drástico.

+0

Pensé en hacerlo de la manera que describe en su primer párrafo, pero eso supone que no hay lagunas en los ID de registro. Creo que este será el caso, y eso puede funcionar. –

3

Por supuesto, su kilometraje variará - Esto dependerá de la cantidad de registros reales que está raspando en la parte inferior de esta tabla, pero aquí hay una alternativa.

Side Nota: Dado que tiene un campo "Date_Added", ¿valdría la pena considerar simplemente mantener el datetime de la última ejecución y usarlo en su cláusula where para filtrar los registros que se eliminarán? Ahora, en lugar de 20.000 registros, permitir que X número de días en el registro ... Es sólo una idea ...


- Obtener los registros que queremos mantener en un temp.
- Puede clasificar a los cuidadores como desee.

select top 20000 * into #myTempTable from MyTable ORDER BY DateAdded DESC 

- Uso truncado no trash nuestro archivo de registro y utiliza menos recursos sys ...

truncate table MyTable 

- Llevar nuestros registros guardados '' de vuelta al redil ...
- Esto supone que no está utilizando una columna de identidad - si usted es, usted debe
- especificar los nombres de campo en lugar de utilizar el algo '*' y hacer como
- SET_IDENTITY_INSERT MiTabla EN
- insertar en MiTabla seleccione campo1, campo2, field3 de #myTempTable
- (creo que es la derecha)

insert into MyTable select * from #myTempTable 

- ser un buen ciudadano.

drop table #myTempTable 


creo que sirve -

3
DECLARE @limit INT 
SELECT @limit = min(id) FROM 
    (SELECT TOP 20000 id FROM your_table ORDER BY id DESC)x 
DELETE FROM your_table where id < @limit 

El punto era evitar la consulta anidada, que puede o no puede ser optimizado gurú (lo siento no sql.)

+0

Tanto este como el enfoque de tabla temporal son ideas geniales en las que nunca hubiera pensado. Amo este sitio –

0

Su pregunta implica que está recortando para obtener un mejor rendimiento diurno de la tabla. ¿Recibes escaneos de tablas en las consultas diurnas? ¿No serían mejores índices la respuesta? ¿O estás en una situación en la que te encuentras atrapado en un "esquema horrible"?

¿O tiene alguna situación realmente extraña en la que de hecho necesita purgar registros antiguos? ¿20,000 es un número difícil y rápido? ¿O podría funcionar una fecha y hora? Luego, e indexar en la columna de fecha y hora facilitaría el recorte.

+0

Originalmente estaba planeando usar una fecha, como eliminar todos los registros anteriores a 2 semanas. Pero el cliente específicamente quería mantener un número exacto en su lugar. Su razonamiento fue que no podemos agotarnos sin ningún problema si algo se complica durante unos días. –

1

inserto 20000 en tabla temporal a continuación, eliminar todos los registros de la tabla principal, de nuevo insertar 20000 registro de la tabla temporal a la tabla principal ..,

Cuestiones relacionadas