2009-06-19 20 views
7

Tengo una tabla bastante grande: más de 20 millones de filas y necesito actualizar aproximadamente el 5% de eso, o 1 millón de filas.¿Cómo acelerar una actualización masiva a la columna agrupada?

Desafortunadamente, estoy actualizando la columna (int) que se está utilizando como el índice agrupado.

Mi pregunta es: ¿Cuál es la forma más rápida de actualizar estas filas?

He intentado actualizar las filas directamente:

update t1 
set t1.groupId = t2.groupId 
from 
    table t1 
join newtable t2 on t1.email = t2.email 

pero esto lleva demasiado tiempo (lo paré después de 3 horas)

que suponer que esto se debe a toda la fila (que tiene 2 datetimes, 2 varchars y 2 ints) se están moviendo para cada actualización.

¿Qué pasa si primero dejo caer el índice agrupado, luego hago las actualizaciones, y luego vuelvo a crear el índice agrupado? ¿Sería eso más rápido?

Nota: Tengo un índice no agrupado en el correo electrónico, en caso de que alguien piense que es la parte seleccionada de la consulta que es lenta. No es.

+2

Creo que ha respondido a su propia pregunta. Además de eliminar el índice agrupado, también puede soltar sus otros índices y volver a crearlos cuando finalice su actualización. –

Respuesta

8

Aquí es lo que hice (y fue mucho más rápido):

  1. me cayó el índice agrupado.
  2. TAMBIÉN he soltado las claves externas referencias (las otras dos columnas int ).
  3. Ejecuté la declaración de actualización
  4. Recreé el índice, que fue más rápido de lo esperado. (Esta es la razón original por la que pregunté SO primero).

Esto llevó todo el proceso a una cuestión de segundos. Sí, ~ 1 millón de filas en unos 15 segundos.

El segundo paso fue crucial porque las claves foráneas forzaron a la actualización a realizar algún tipo de spool en las tablas relacionadas, que también tienen una gran cantidad de filas.

El número de lecturas físicas se triplicó debido a estas búsquedas de claves externas.

No estoy seguro de por qué SQL Server necesita hacer eso, pero creo que todavía realiza la verificación de integridad incluso si no estoy actualizando esa columna pero estoy moviendo toda la fila (actualización de columna en clúster).


Como nota al margen, también había tratado de ejecutar la actualización en lotes:

update top(1000) t1 
set t1.groupId = t2.groupId 
from 
    table t1 
join newtable t2 on t1.email = t2.email 

Esto estaba bien (y parecía escalar hasta aproximadamente 10 K por lote) pero todavía estaba en el orden de 1-2 minutos cada lote.


En resumen, he aprendido que para las actualizaciones masivas, la eliminación temporal de índices puede ser muy útil.

-1

¿Por qué no hacer lo siguiente:

  • Hacer una columna diferente (uno de los varchar de) el índice agrupado
  • Crear un índice en su groupId
  • actualización
  • luego invertir el proceso.

Esto debería ser más rápido.

+1

¿Por qué debería hacer una columna diferente del índice agrupado? ¿No aleatorizaría de manera efectiva mis groupIds y haría que fuera más lento volver a crear el índice clusterId clustered? Este era mi miedo –

2

Creo que el comentario anterior es correcto. Usted ha respondido su propia pregunta.

Debido

Los índices agrupados ordenar y almacenar los filas de datos en la tabla de la base de sus valores clave (fuente MSDN),

que puede ser mejor simplemente dejar caer el índice agrupado (mantener el índice en el correo electrónico). Cuando finaliza la operación, recrea el índice agrupado. Siempre que groupid no esté involucrado en ningún otro índice, no los tocaría. Si la identificación del grupo está involucrada en otros índices, colóquelos. Dejaría al menos un índice en el correo electrónico, solo para hacer la unión rápidamente.

Cuestiones relacionadas