2009-06-05 61 views
36

Delete s en el servidor sql a veces son lentos y con frecuencia he necesitado optimizarlos para disminuir el tiempo necesario. He estado buscando un poco de google buscando consejos sobre cómo hacerlo, y he encontrado diversas sugerencias. Me gustaría conocer sus técnicas favoritas y más efectivas para domesticar a la bestia eliminada, y cómo y por qué funcionan.Optimizar Eliminar en SQL Server

hasta ahora:

  • claves externas seguro que tienen índices

  • asegurarse de que las condiciones en las que se indexan

  • uso de WITH ROWLOCK

  • destruir índices no utilizados, eliminar , reconstruya los índices

ahora, su turno.

+0

Pregunta a los usuarios avanzados: esta pregunta no tiene una sola respuesta, es más una especie de base de conocimiento que una simple pregunta-respuesta. ¿Puede ser que se convierta en una wiki comunitaria? (si entiendo bien para qué sirve c.w.) – pomarc

+0

Me gustaría verlo como un resumen en curso. Esta publicación fue muy útil para mí, pero me llevó horas leer las sugerencias. He enviado una edición con un nuevo resumen que fue rechazado, esperando ver si se realiza el segundo intento :) – xero

+0

@xero Revertí la edición, puede marcar a un administrador para llamar la atención (usar otro) después de leer [Si el ¿La policía wiki de la comunidad se cerrará?] (http://meta.stackexchange.com/questions/392/should-the-community-wiki-police-be-shut-down) [¿Qué podemos hacer para mejorar Community Wiki? ] (http://meta.stackexchange.com/questions/67039/what-can-we-do-to-make-community-wiki-better) y http://meta.stackoverflow.com/a/266921 – bummi

Respuesta

21

El siguiente artículo, operaciones de borrado ordenado rápido puede ser de su interés.

Performing fast SQL Server delete operations

La solución se centra en la utilización de un punto de vista con el fin de simplificar el plan de ejecución producida por lotes para una operación de eliminación. Esto se logra al hacer referencia a la tabla dada una vez, en lugar de dos veces, lo que a su vez reduce la cantidad de E/S requerida.

+1

El documento original ya no está disponible en el enlace especificado, pero el enlace está disponible en forma de archivo aquí: https://web.archive.org/web/20100212155407/http://blogs.msdn.com/ sqlcat/archive/2009/05/21/fast-ordered-delete.aspx (sugerencia de sombrero a William Isted a través de https://www.codelibrary.me/2012/08/01/perform-fast-mssql-delete-operations/) – Dragonsdoom

12

que tienen mucha más experiencia con Oracle, pero muy probable que lo mismo se aplica a SQL Server, así:

  • cuando se elimina un gran número de filas, emitir un bloqueo de tabla, por lo que la base de datos no tiene para hacer muchos bloqueos de fila
  • si la tabla que elimina se referencia en otras tablas, asegúrese de que esas otras tablas tengan índices en las columnas de clave externa (de lo contrario la base de datos realizará una exploración de tabla completa por cada eliminada fila en la otra tabla para asegurarse de que eliminar la fila no infringe la restricción de clave externa)
+2

bloqueo de tabla evitaría insertar y actualizar en la tabla, necesita asegurarse de que la eliminación sea rápida antes de que otras transacciones comiencen a agotar el tiempo de espera. – dsum

+0

dsum: cierto, pero eliminar una gran cantidad de registros es algo que generalmente sucede en una ventana de mantenimiento sin otra actividad (por ejemplo, de noche). –

4

(si los índices son "sin usar", ¿por qué están allí?)

Una de las opciones que he usado en el pasado es para hacer el trabajo por lotes. La forma más simple sería usar SET ROWCOUNT 20000 (o lo que sea) y buclear (quizás con un WAITFOR DELAY) hasta que se deshaga de todo (@@ ROWCOUNT = 0).

Esto podría ayudar a reducir el impacto en otros sistemas.

+0

"sin usar" en la eliminación – pomarc

+0

Pero usualmente hay más cosas sucediendo que simplemente eliminar ... Supongo que puede ser útil, pero debe verificar que no empeore (en general) el sistema. –

+0

¡No elimine índices simplemente porque no se utilizan en la eliminación! ¡Otras personas están usando la base de datos para otras cosas! – HLGEM

5

Para ser sincero, eliminar un millón de filas de una tabla aumenta tan mal como insertar o actualizar un millón de filas. El problema es el tamaño del conjunto de filas, y no hay mucho que puedas hacer al respecto.

Mis sugerencias:

  • Asegúrese de que la tabla tiene una clave principal y índice agrupado (esto es vital para todas las operaciones).
  • Asegúrese de que el índice agrupado sea tal que se produzca una reorganización mínima de la página si se eliminara un bloque grande de filas.
  • Asegúrate de que tus criterios de selección sean SARGables.
  • Asegúrate de que todas tus restricciones de clave externa sean actualmente confiables.
+8

SARGable: en las bases de datos relacionales, se dice que una condición (o predicado) en una consulta es sargable si el motor DBMS puede aprovechar un índice para acelerar la ejecución de la consulta (utilizando índices buscados, sin cubrir índices). El término se deriva de una contracción de Search ARGument Able. (Wikipedia) – pomarc

2

voy a añadir otra a esto:

Asegúrese de que sus opciones de nivel de aislamiento de transacciones y bases de datos se establecen de manera apropiada. Si su servidor SQL está configurado para no usar el control de versiones de filas, o está usando un nivel de aislamiento en otras consultas donde esperará a que se eliminen las filas, podría estarse configurando para un rendimiento muy bajo mientras la operación está ocurriendo. .

2

En tablas muy grandes donde tiene un conjunto muy específico de criterios para las eliminaciones, también puede dividir la tabla, cambiar la partición y luego procesar las eliminaciones.

El equipo de SQLCAT ha estado utilizando esta técnica en realmente realmente grandes volúmenes de datos. Encontré algunas referencias al here pero intentaré encontrar algo más definitivo.

3

Si tiene muchas tablas de claves externas, comience en la parte inferior de la cadena y avance. La eliminación final irá más rápido y bloqueará menos cosas si no hay registros secundarios para eliminar en cascada (que NO activaría si tuviera un número grande de tablas secundarias, ya que eso mataría el rendimiento).

Eliminar por lotes.

Si tiene tablas de claves externas que ya no se utilizan (le sorprenderá la frecuencia con la que los databs de producción terminan en tablas antiguas de las que nadie se va a deshacer), deshágase de ellos o al menos rompa el FK/PK conexión. No tiene sentido marcar una tabla para los registros si no se está utilizando.

No eliminar: marque registros como delted y luego excluya los registros marcados de todas las consultas. Esta es la mejor configuración en el momento del diseño de la base de datos. Mucha gente usa esto porque también es la mejor forma de recuperar registros borrados accidentalmente. Pero es mucho trabajo para configurar en un sistema ya existente.

1

Hay eliminaciones y luego hay eliminaciones. Si está agotando los datos como parte de un trabajo de recorte, con suerte podrá eliminar bloques contiguos de filas mediante la clave agrupada. Si tiene que superar los datos de una tabla de alto volumen que no es contigua, es muy doloroso.

1

Si es cierto que las ACTUALIZACIONES son más rápidas que las DELETES, puede agregar una columna de estado llamada DELETED y filtrarla en sus selecciones. A continuación, ejecute un proceso por la noche que elimina las eliminaciones reales.

9

Me pregunto si es hora de recoger basura en las bases de datos? Marca una fila para eliminarla y el servidor la elimina más adelante durante un barrido. No querría esto para cada eliminación, porque a veces una fila debe irse ahora, pero sería útil en ocasiones.

+0

Me gusta la idea de eso. Puede implementar esto, simplemente marque un bit, To_be_delted y luego ejecute una consulta de vez en cuando para eliminar estos valores. Pero acepto que un sistema automático de recolección de basura sería genial – Zapnologica

+2

Eliminar una fila significa al menos tres cosas: a) asegurarse de que ninguna restricción de clave externa sea violada por la eliminación b) marcar el espacio ocupado por la fila como "disponible". c) eliminar la fila de todos los índices en esa tabla. De estos, a) puede ser el más caro (si las tablas de referencia no tienen un índice en las columnas de clave externa) pero debe hacerse de inmediato, por lo que puede decirle al usuario "no puede eliminar esta fila, todavía está referenciado ". b) es probablemente barato yc) generalmente no es tan caro. Por lo tanto, no estoy convencido de esta idea. –

4

El problema es que no ha definido sus condiciones lo suficiente. Es decir. ¿Qué estás optimizando exactamente?

Por ejemplo, ¿está apagado el sistema para el mantenimiento nocturno y no hay usuarios en el sistema?¿Y borras un gran% de la base de datos?

Si está fuera de línea y elimina un gran%, puede tener sentido crear una nueva tabla con datos para guardar, descartar la tabla anterior y renombrarla. Si elimina un% pequeño, es probable que desee agrupar las cosas en lotes tan grandes como lo permita su espacio de registro. Depende completamente de su base de datos, pero la caída de índices durante la reconstrucción puede dañar o ayudar, incluso si es posible debido a estar "fuera de línea".

Si está en línea, ¿cuál es la probabilidad de que sus eliminaciones entren en conflicto con la actividad del usuario (y la actividad del usuario es principalmente leer, actualizar o qué)? ¿O está tratando de optimizar la experiencia del usuario o la velocidad de hacer su consulta? Si está eliminando de una tabla que otros usuarios actualizan con frecuencia, debe hacerlo por lotes pero con tamaños de lote más pequeños. Incluso si hace algo así como un bloqueo de tabla para forzar el aislamiento, eso no sirve de mucho si su enunciado de eliminación demora una hora.

Cuando define mejor sus condiciones, puede elegir una de las otras respuestas aquí. Me gusta el enlace en la publicación de Rob Sanders para dosificar cosas.

+0

gracias matt. bueno, mi pregunta es bastante general, he tenido eliminaciones lentas en varias y diferentes ocasiones, y esta fue una manera de reunir los consejos que la gente podría compartir sobre el tema. – pomarc

1

¿Tiene teclas externas con integridad referencial activada? ¿Tiene disparadores activos?

2

Creo que la gran trampa con eliminación que mata el rendimiento es que sql después de eliminar cada fila, actualiza todos los índices relacionados para cualquier columna en esta fila. ¿Qué hay de delting todos los índices antes de la eliminación masiva?

5

Resumen de las respuestas a través 2014-11-05

Esta respuesta se marca como wiki de la comunidad ya que este es un tema en constante evolución con una gran cantidad de matices, pero muy pocas respuestas posibles general.

El primer problema es que debe preguntarse qué escenario está optimizando para? En general, esto es rendimiento con un solo usuario en la base de datos o escala con muchos usuarios en la base de datos. Algunas veces las respuestas son exactamente lo opuesto.

Para la optimización de un solo usuario

  • Hint un TABLELOCK
  • Retire los índices no utilizados en el borrar y reconstruirlos después
  • por lotes usando algo como SET ROWCOUNT 20000 (o lo que sea, dependiendo de espacio de registro) y bucle (quizás con un WAITFOR DELAY) hasta que se deshaga de todo (@@ROWCOUNT = 0)
  • Si borra un% grande de la tabla, simplemente ma ke uno nuevo y elimine la tabla anterior
  • Particione las filas para eliminar, luego suelte la parición.[Read more...]

Para la optimización multi-usuario

  • fila Indirecta cerraduras
  • utilizar el índice agrupado
  • Diseño índice agrupado para minimizar la página reorganización si grandes bloques se eliminan
  • actualización columna "is_deleted", luego realice la eliminación real más tarde durante una ventana de mantenimiento

Para la optimización general de

  • Asegúrese FKs tienen índices de sus tablas de origen
  • Asegúrese WHERE cláusula tiene índices
  • Identificar los registros a borrar en la cláusula WHERE con una vista o derivados tabla en lugar de hacer referencia directamente a la tabla. [Read more...]
-1

¡Simplifique cualquier uso de funciones en su cláusula WHERE! Ejemplo:

DELETE FROM Claims 
WHERE dbo.YearMonthGet(DataFileYearMonth) = dbo.YearMonthGet(@DataFileYearMonth) 

Esta forma de la cláusula WHERE requiere 8 minutos para eliminar 125,837 registros.

La función YearMonthGet compuso una fecha con el año y el mes a partir de la fecha de entrada y establece day = 1. Esto fue para asegurarnos de eliminar los registros en función del año y el mes, pero no del día del mes.

Reescribí la cláusula WHERE para:

WHERE YEAR(DataFileYearMonth) = YEAR(@DataFileYearMonth) 
AND MONTH(DataFileYearMonth) = MONTH(@DataFileYearMonth) 

El resultado: la eliminación requerida acerca de 38-44 segundos para borrar los registros de 125,837!

Cuestiones relacionadas