De todo lo que puedo ver, no parece que sus problemas estén relacionados con los índices.
La clave parece estar en el hecho de que su campo nvarchar (max) contiene "muchos" datos. Piense en lo que SQL tiene que hacer para realizar esta actualización.
Dado que la columna que está actualizando probablemente tenga más de 8000 caracteres, se almacena fuera de página, lo que implica un esfuerzo adicional en la lectura de esta columna cuando no es NULA.
Cuando ejecuta un lote de 50000 actualizaciones, SQL tiene que colocar esto en una transacción implícita para posibilitar la reversión en caso de problemas. Para revertir tiene que almacenar el valor original de la columna en el registro de transacciones.
Suponiendo (por simplicidad) que cada columna contiene un promedio de 10,000 bytes de datos, eso significa que 50,000 filas contendrán alrededor de 500MB de datos, que deben almacenarse temporalmente (en modo de recuperación simple) o permanentemente (en recuperación completa modo).
No hay forma de desactivar los registros, ya que comprometerá la integridad de la base de datos.
Realicé una prueba rápida en el escritorio lento de mi perro, y ejecutar lotes de incluso 10.000 se vuelve extremadamente lento, pero reducir el tamaño a 1000 filas, lo que implica un tamaño de registro temporal de 10 MB funcionó muy bien.
Cargué una tabla con 350,000 filas y marqué 50,000 para actualizar. Esto se completó en alrededor de 4 minutos, y como se escala linealmente, debería poder actualizar sus 5 millones de filas en mi escritorio lento para perros en alrededor de 6 horas en mi escritorio de 1GB de 2GB, así que esperaría algo mucho mejor en su fornido servidor respaldado por SAN o algo así.
Es posible que desee ejecutar su declaración de actualización como una selección, seleccionando solo la clave principal y la columna nvarchar grande, y asegúrese de que esto se ejecute tan rápido como esperaba.
Por supuesto, el cuello de botella puede ser que otros usuarios bloqueen cosas o contención en su almacenamiento o memoria en el servidor, pero como no mencionó a otros usuarios supondré que tiene la base de datos en modo de usuario único para esto.
Como optimización, debe asegurarse de que los registros de transacciones estén en un disco físico/grupo de discos diferente de los datos para minimizar los tiempos de búsqueda.
Vea también: http://stackoverflow.com/questions/571750/make-sql-server-faster-at-manipulating-data-turn-off-transaction-logging –
¿Cómo está haciendo los registros de lotes '50K en una actualización de tiempo? ¿Es con un procedimiento almacenado? Si es así, ¿puedes poner el código? – Fede
@ user356004: al volver a leer No puedo evitar pensar que su servidor está bajo mucha carga o que no está configurado correctamente: esos tiempos parecen muy altos. –