2010-01-15 19 views
5

Estoy ejecutando un script de archivo que elimina las filas de un gran (~ 50m base de datos de registro) en función de la fecha en que se ingresaron. El campo de fecha es el índice agrupado de la tabla y, por lo tanto, a qué estoy aplicando mi declaración condicional.sql server delete ralentizado drásticamente por los índices

Estoy ejecutando esta eliminación en un ciclo while, intentando cualquier cosa entre 1000 y 100.000 registros en un lote. Independientemente del tamaño del lote, es sorprendentemente lento; algo así como 10.000 registros que se eliminan por minuto. En cuanto al plan de ejecución, hay mucho tiempo dedicado a "Eliminar índice". Hay aproximadamente 15 campos en la tabla, y aproximadamente 10 de ellos tienen algún tipo de índice. ¿Hay alguna forma de evitar este problema? Ni siquiera estoy seguro de por qué lleva tanto tiempo eliminar cada índice, ¿alguien puede arrojar algo de luz sobre qué está pasando exactamente aquí? Esta es una muestra de mi plan de ejecución:

alt text http://img94.imageshack.us/img94/1006/indexdelete.png

(Los puntos de secuencia para el comando Eliminar)

Esta base de datos está vivo y se está insertado en frecuencia, por lo que estoy indeciso a utilice el método de copiar y truncar para recortar el tamaño. ¿Hay alguna otra opción que me falta aquí?

+2

¿Es completamente necesario tener todos estos índices? Si no está usando los índices, debería deshacerse de ellos. –

+0

Acabo de hablar con el programador principal en nuestro sitio, y parece que probablemente ya no los necesitemos todos. Si bien hacemos algunas consultas sobre la mesa, es mucho más utilizado como una tabla de tipo registro. Puedo tratar de soltar algunas inserciones antes de volver a ejecutar el script de eliminación. – Kevin

Respuesta

1

Más de una solución alternativa, pero ¿puede agregar un indicador IsDeleted a la tabla y actualizarlo a 1 en lugar de eliminar las filas? Tendrá que modificar su SELECTs y UPDATEs para usar esta bandera.

Luego puede programar la eliminación o el archivado de estos registros para fuera de horario.

+0

Bueno, tengo la intención de ejecutar este script regularmente fuera de las horas diarias para mantener el ajuste de la base de datos (elimina cualquier registro anterior a 2 años), pero la ejecución inicial es tan lenta que tomaría aproximadamente 4 horas completarla actualmente, lo cual es más de lo que los poderosos quieren tener atados al servidor. ¡Gracias por la sugerencia! – Kevin

+1

En ese caso simplemente elimine lotes más pequeños a la vez (por ejemplo, 1,000) para que no haya un impacto perceptible en la carga del servidor desde la perspectiva del usuario final, y repita esto con un retraso de 30-60 segundos entre cada ciclo. Entonces solo déjalo funcionar hasta que esté hecho. Podría tomar una semana o dos, pero debería hacer el trabajo. – RedFilter

1

Tomaría algún trabajo implementarlo dado que está en producción, pero si está en SQL Server 2005/2008 debe investigar y convertir la tabla para particionar, entonces la eliminación de datos antiguos se puede lograr extremadamente rápido . Está diseñado para un efecto tipo 'ventana rodante' y evita eliminaciones a gran escala que vinculan una tabla/proceso.

Desafortunadamente, con la tabla en producción, migrarla a esta técnica requerirá cierta codificación T-SQL, conocimiento y un fin de semana para actualizarla/migrarla. Una vez que esté instalado, aunque las selecciones y las inserciones existentes trabajarán en su contra sin problemas, el mantenimiento y la adición/eliminación de la partición es donde necesita el t-sql para controlar el proceso.

2

En segundo lugar la sugerencia que @NickLarsen hizo en un comentario. Averigüe si tiene unused indexes y suéltelos. Esto podría reducir la sobrecarga de las eliminaciones de índice, lo que podría ser una mejora suficiente para que la operación sea más oportuna.

Otra estrategia más radical es eliminar todos los índices, realizar las eliminaciones y luego volver a crear rápidamente los índices para el conjunto de datos ahora más pequeño. Esto no necesariamente interrumpe el servicio, pero probablemente haga las consultas mucho más lentas mientras tanto. Aunque no soy un experto en Microsoft SQL Server, por lo que debe tomar mi consejo sobre esta estrategia con un grano de sal.

3

Supongamos que para cada registro en la tabla hay 5 registros de índice.

Ahora cada eliminación es en esencia 5 operaciones.

Agregue a eso, usted tiene un índice agrupado. Tenga en cuenta que el tiempo de eliminación del índice agrupado es enorme. (10x) más largo que los otros índices? Esto se debe a que sus datos se están reorganizando con cada registro eliminado.

Sugeriría eliminar al menos ese índice, haciendo una eliminación masiva, que volver a aplicar. Las operaciones de índice en eliminar e insertar son intrínsecamente costosas. Una única reconstrucción es probablemente mucho más rápida.

6

Suprimir 10k registros de un índice agrupado + 5 no agrupados definitivamente no debería tomar 1 minuto. Parece que tienes un subsistema IO realmente muy lento. ¿Cuáles son los valores de:

  • Precio medio Disco seg./Escribir
  • Precio medio. Seg. De disco/Leer
  • Precio medio Longitud de cola de escritura de disco
  • Precio medio. Longitud de la cola de lectura del disco

En cada unidad implicada en la operación (incluidos los registros!). Si coloca índices en grupos de archivos separados y asigna cada grupo de archivos a su propio LUN o disco propio, puede identificar qué índices son más problemáticos. Además, el enjuague del tronco puede ser un importante cuello de botella. SQL Server no tiene mucho control aquí, está todo en sus manos cómo acelerar las cosas. ese tiempo no se gasta en ciclos de CPU, se gasta esperando a que IO lo complete y necesita un subsistema IO calibrado para la carga que usted demanda.

Para reducir la carga de IO, debe considerar hacer los índices más estrechos. En primer lugar, asegúrese de que el índice agrupado sea el más estrecho posible que funcione. Luego, asegúrese de que los índices no agrupados no incluyan grandes columnas no utilizadas (he visto eso ...). Se puede obtener una ganancia importante habilitando page compression. Y finalmente, inspeccione las estadísticas de uso del índice en sys.dm_db_index_usage_stats y vea si algún índice es bueno para el hacha.

Si no puede reducir mucho la carga de IO, intente dividirla. Agregue grupos de archivos a la base de datos, mueva índices grandes en grupos de archivos separados, coloque los grupos de archivos en rutas IO separadas (husos distintos).

Para futuras operaciones de eliminación regular, la mejor alternativa es usar la conmutación de partición, tener todos los índices alineados con el particionamiento de índice agrupado y, llegado el momento, simplemente colocar la última partición para una eliminación rápida.

+0

Estoy bastante seguro de que el hardware es más que capaz. Tenemos SSD de Intel por separado para el registro y los datos, y otro para el sistema operativo. Tiene dos procesadores Xeon de cuatro núcleos y 16 GB de memoria DDR3. Terminamos corriendo esto en el transcurso del fin de semana para limpiar las ~ 25m filas. Ahora lo ejecutaremos todas las noches para mantener el DB limpio y agradable, y solo debería tomar uno o dos minutos. – Kevin

+8

¿Estás tan seguro de que ni siquiera vas a medir? –

Cuestiones relacionadas