Tenemos un proceso que genera un informe de inventario. En el lado del cliente, el proceso se divide en un número configurable de subprocesos de trabajo para generar una porción de datos para el informe que corresponde a un almacén de muchos (potencialmente miles, generalmente docenas). Cada subproceso de trabajo llama a un servicio web que ejecuta un procedimiento almacenado.
El proceso de la base de datos para procesar cada fragmento reúne un conjunto de datos en una tabla #Temporary. Al final de cada fragmento de procesamiento, los datos se escriben en una tabla permanente en tempdb. Finalmente, al final del proceso, un hilo en el lado del cliente solicita todos los datos de la tabla temporal tempdb.
Cuantos más usuarios ejecuten este informe, más lento será. Analicé la actividad en la base de datos. En un momento, vi 35 solicitudes separadas, todas bloqueadas en un punto del proceso. Todos estos SPID tenían del orden de 50 ms esperas de tipo LATCH_EX
en recurso METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)
. Un SPID tiene este recurso, y todos los demás están bloqueando. No encontré nada sobre este recurso de espera en una búsqueda web.
La tabla en tempdb que estamos usando tiene una IDENTITY(1,1)
columna. ¿Están estos SPID esperando la columna IDENTIDAD? ¿Qué métodos podríamos usar para reducir o eliminar el bloqueo?
El servidor es parte de un clúster. El servidor ejecuta SQL Server 2012 Standard Edition SP1 de 64 bits en Windows 2008 R2 Enterprise de 64 bits. El servidor tiene 64 GB de RAM y 48 procesadores, pero la base de datos solo puede usar 16 porque es la edición estándar.
(Tenga en cuenta que no estoy entusiasmado con el diseño de usar una tabla permanente en tempdb para contener todos estos datos. Cambiar eso sería un desafío técnico y político interesante, pero estoy abierto a sugerencias).
ACTUALIZACIÓN 23/04/2013
Hemos abierto un caso de soporte con Microsoft. Mantendré esta pregunta actualizada a medida que aprendamos más.
ACTUALIZACIÓN 10/05/2013
El ingeniero de soporte de SQL Server acordó que las esperas fueron causadas por la columna IDENTIDAD. Eliminar la IDENTIDAD eliminó las esperas. No pudimos duplicar el problema en SQL 2008 R2; ocurrió solo en SQL 2012.
fuente
Respuestas:
Suponiendo que puede aislar el problema a la generación de valores de identidad (intente eliminar esa columna como prueba), lo que recomendaría es esto:
IDENTITY
propiedad de la columna en la tabla final.Entonces, si tiene los identificadores de tienda 3 y 4, terminaría con valores de identificación finales como este:
O algo similar a eso. Tienes la idea.
Esto eliminará la necesidad de serializar en la
IDENTITY
generación al tiempo que conserva la unicidad en el resultado final.Alternativamente, dependiendo de cómo funcione el proceso, inserte los valores finales de identificación calculados en las tablas #Temporary. Luego, podría crear una vista que
UNION ALL
los una a la vez, eliminando la necesidad de copiar los datos.fuente
IDENTITY
columna. Lo quitamos del índice agrupado ya ancho y eliminamos la columna por completo. No era necesario. Después, estas esperas LATCH_EX desaparecieron. No pudimos duplicar las esperas en SQL 2008 R2. El problema ocurrió solo en SQL Server 2012.IDENTITY
valores se reescribió para usar el nuevo material de generación de secuencias que era nuevo en 2012. En <2012, puede ver un tipo de bloqueo diferente, aunque si no hubo un problema de rendimiento, entonces parece que hubo Una regresión en el código. En cualquier caso, eliminar laIDENTITY
columna es lo más seguro.(Actualizado en febrero de 2019)
Esta es una publicación antigua, que decía que finalmente logré convencer a Microsoft de que el hecho de que esto ocurra es realmente un defecto.
Actualización: MS confirmó el defecto y le asignó un número de error # 12628722.
Había visto esta publicación el pasado noviembre de 2018 cuando comenzamos a sufrir lo mismo después de haber actualizado de Sql Server 2005 a Sql Server 2017. Una tabla de 3.3 millones de filas que solía tomar 10 segundos para la inserción masiva de repente comenzó a tomar 10 minutos en tablas con
Identity
columnas.Resulta que hay dos problemas detrás de esto:
Me tomó 4 semanas, pero justo después de las vacaciones recibí un regalo tardío de Santa, confirmación de que el problema era realmente un defecto.
Hay algunas soluciones posibles que encontramos hasta que se solucione esto:
Option (MaxDop 1)
en la consulta para convertir el inserto masivo nuevamente en un plan serializado.Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn
. Ej. )SELECT...INTO
Actualización: La solución que MS implementará será devolver este tipo de inserciones para volver a usar un
Serialized
plan. Esto está planeado para Sql Server 2017 CU14 (no hay noticias sobre otras versiones de Sql Server, ¡lo siento!). Cuando se implemente, será necesario activar Trace Flag 9492 , ya sea a nivel del servidor o medianteDBCC TraceOn
.fuente