2010-01-26 14 views
8

Supongamos que tengo una tabla con 10000000 de registro. ¿Cuál es la diferencia entre estas dos soluciones?Eliminar gran cantidad de datos en el servidor sql

  1. datos de borrado como:

    DELETE FROM MyTable 
    
  2. borrar todos los datos con una fila por fila aplicación:

    DELETE FROM MyTable WHERE ID = @SelectedID 
    

es la primera solución tiene mejor rendimiento? ¿cuál es el impacto en el registro y el rendimiento?

Respuesta

14

Si tiene tantos registros en la tabla y desea eliminarlos a todos, debe considerar truncate <table> en lugar de delete from <table>. Será mucho más rápido, pero tenga en cuenta que no puede activar un disparador.

Ver para más detalles (este caso el servidor SQL 2000): http://msdn.microsoft.com/en-us/library/aa260621%28SQL.80%29.aspx

Eliminación de la mesa dentro de la fila aplicación por fila va a terminar en mucho, mucho tiempo, ya que su DBMS no pueden optimizar nada, ya no sabe de antemano, que va a eliminar todo.

+4

Puede revertir un truncado si todavía está dentro del alcance de la transacción que realizó, contrario a la creencia popular de que está transaccionalizado, el IAM desasignado es no se elimina hasta la confirmación, por lo que se puede revertir restableciendo el IAM. – Andrew

+0

Solo léalo, y tiene razón, en el servidor SQL puede revertir un truncado. Tenía en mente el oráculo donde no es posible (según la documentación). –

+0

No puedo usar TRUNCATE porque MyTable tiene una clave foránea, también necesito la cláusula WHERE para los datos de filtro –

3

El primero tiene claramente un mejor rendimiento.

Cuando especifica DELETE [MyTable], simplemente borrará todo sin realizar comprobaciones de identificación. El segundo perderá tiempo y operación del disco para localizar un registro respectivo cada vez antes de eliminarlo.

También empeora porque cada vez que un registro desaparece de la mitad de la tabla, el motor puede querer condensar datos en el disco, perdiendo tiempo y trabajando de nuevo.

Quizás una mejor idea sería eliminar datos basados ​​en columnas de índice agrupados en orden descendente. Entonces, la tabla básicamente se truncará desde el final en cada operación de eliminación.

+0

por favor, dígame por qué. –

+0

dices que: "Quizás una mejor idea sería eliminar los datos basados ​​en columnas de índice en clúster en orden descendente. Luego, la tabla se truncará básicamente desde el final en cada operación de eliminación". ¿Puedes describir más? –

+0

El motor de base de datos asigna datos físicamente en el disco en el orden de disco en clúster. Si eliminase registros con los valores de índice más altos, eso básicamente llevaría a cortar la cola del archivo, sin condensar los datos que podrían ocurrir si elimina algo en el medio del archivo. Esto es especialmente importante cuando agrega registros para intentar que se anexen al final del archivo. Me imagino que eliminar registros del final también mejoraría el rendimiento. –

3

La opción 1 creará una transacción muy grande y tendrá un gran impacto en el registro/rendimiento, así como en los bloqueos en aumento para que la tabla no esté disponible. La opción 2 será más lenta, aunque generará menos impacto en el registro (suponiendo el modo bulk/full)

Si desea deshacerse de todos los datos, Truncate Table MyTable sería más rápido que los dos, aunque tiene no hay posibilidad de filtrar filas, hace un cambio de metadatos en la parte posterior y básicamente descarta el IAM en el piso para la tabla en cuestión.

+0

No puedo usar TRUNCATE porque MyTable tiene una clave externa, también necesito la cláusula WHERE para datos de filtro –

0

El primero será eliminar todas los datos de la tabla y tendrá un mejor rendimiento que su segundo, que eliminará sólo datos de una clave específica.

Ahora bien, si usted tiene que borrar todos los datos de la tabla y no se basan en el uso de pensar reversión de la utilización de un truncate table

21

Si necesita restringir a lo filas que necesita para eliminar y no hacer una completa eliminación, o no se puede utilizar TRUNCATE TABLE (por ejemplo, la tabla está referenciada por una restricción FK, o incluido en una vista indizada), entonces usted puede hacer el eliminar en trozos:

DECLARE @RowsDeleted INTEGER 
SET @RowsDeleted = 1 

WHILE (@RowsDeleted > 0) 
    BEGIN 
     -- delete 10,000 rows a time 
     DELETE TOP (10000) FROM MyTable [WHERE .....] -- WHERE is optional 
     SET @RowsDeleted = @@ROWCOUNT 
    END 

en general, TRUNCATE es la mejor manera y lo usaría si fuera posible. Pero no puede usarse en todos los escenarios. Además, tenga en cuenta que TRUNCATE restablecerá el valor de IDENTIDAD para la tabla, si la hay.

Si está utilizando SQL 2000 o anterior, la condición TOP no está disponible, por lo que puede usar SET ROWCOUNT en su lugar.

DECLARE @RowsDeleted INTEGER 
SET @RowsDeleted = 1 
SET ROWCOUNT 10000 -- delete 10,000 rows a time 

WHILE (@RowsDeleted > 0) 
    BEGIN 
     DELETE FROM MyTable [WHERE .....] -- WHERE is optional 
     SET @RowsDeleted = @@ROWCOUNT 
    END 
+2

Es posible que desee evitar el uso de SET ROWCOUNT a favor de SELECT/INSERT/UPDATE/DELETE TOP (N) ... ¿El motivo? Eche un vistazo aquí: http://msdn.microsoft.com/en-us/library/ms143729.aspx y aquí: https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=282528 –

+0

Buen punto (suponiendo SQL 2005 o posterior) que probablemente sea una apuesta segura. Actualizado mi respuesta – AdaTheDev

0

Encontrado post on Microsoft TechNet.

Básicamente, se recomienda:

  1. Mediante el uso de SELECT INTO, copiar los datos que desea mantener a una tabla intermedia;
  2. Truncar la tabla fuente;
  3. Copia de nuevo con INSERT INTO de la tabla intermedia, los datos a la tabla fuente;

..

BEGIN TRANSACTION 

SELECT * 
    INTO dbo.bigtable_intermediate 
    FROM dbo.bigtable 
    WHERE Id % 2 = 0; 

    TRUNCATE TABLE dbo.bigtable; 

    SET IDENTITY_INSERT dbo.bigTable ON; 
    INSERT INTO dbo.bigtable WITH (TABLOCK) (Id, c1, c2, c3) 
    SELECT Id, c1, c2, c3 FROM dbo.bigtable_intermediate ORDER BY Id; 
    SET IDENTITY_INSERT dbo.bigtable OFF; 
ROLLBACK TRANSACTION 
Cuestiones relacionadas