¿Hay alguna manera de evitar el punto muerto mientras se mantienen las mismas consultas?
El gráfico de punto muerto muestra que este punto muerto en particular era un punto muerto de conversión asociado con una búsqueda de marcadores (una búsqueda RID en este caso):
Como señala la pregunta, el riesgo general de punto muerto surge porque las consultas pueden obtener bloqueos incompatibles en los mismos recursos en diferentes órdenes. La SELECT
consulta debe acceder al índice antes de la tabla debido a la búsqueda de RID, mientras que la UPDATE
consulta primero modifica la tabla y luego el índice.
Eliminar el punto muerto requiere eliminar uno de los ingredientes del punto muerto. Las siguientes son las principales opciones:
- Evite la búsqueda de RID haciendo que el índice no agrupado cubra. Probablemente esto no sea práctico en su caso porque la
SELECT
consulta devuelve 26 columnas.
- Evite la búsqueda de RID creando un índice agrupado. Esto implicaría crear un índice agrupado en la columna
Proposal
. Vale la pena considerar esto, aunque parece que esta columna es de tipo uniqueidentifier
, lo que puede o no ser una buena opción para un índice agrupado, dependiendo de cuestiones más amplias.
- Evitar tomar bloqueos compartidos cuando se lee al permitir que los
READ_COMMITTED_SNAPSHOT
o SNAPSHOT
de bases de datos opciones. Esto requeriría una prueba cuidadosa, especialmente con respecto a cualquier comportamiento de bloqueo diseñado. El código de activación también requeriría pruebas para garantizar que la lógica funcione correctamente.
- Evite tomar bloqueos compartidos al leer utilizando el
READ UNCOMMITTED
nivel de aislamiento para la SELECT
consulta. Se aplican todas las advertencias habituales.
- Evite la ejecución concurrente de las dos consultas en cuestión mediante el uso de un bloqueo exclusivo de la aplicación (consulte sp_getapplock ).
- Use sugerencias de bloqueo de tabla para evitar la concurrencia. Este es un martillo más grande que la opción 5, ya que puede afectar otras consultas, no solo las dos identificadas en la pregunta.
¿De alguna manera puedo tomar un X-Lock en el índice en la transacción de actualización antes de la actualización para asegurar que la tabla y el acceso al índice estén en el mismo orden
Puede probar esto, envolviendo la actualización en una transacción explícita y realizar una SELECT
con una XLOCK
pista sobre el valor del índice no agrupado antes de la actualización. Esto depende de que usted sepa con certeza cuál es el valor actual en el índice no agrupado, que obtenga el plan de ejecución correcto y que anticipe correctamente todos los efectos secundarios de tomar este bloqueo adicional. También se basa en que el motor de bloqueo no es lo suficientemente inteligente como para evitar tomar el bloqueo si se considera redundante .
En resumen, si bien esto es factible en principio, no lo recomiendo. Es demasiado fácil perderse algo, o burlarse de uno mismo de manera creativa. Si realmente debe evitar estos puntos muertos (en lugar de solo detectarlos y volver a intentarlos), le animo a que busque en su lugar las soluciones más generales enumeradas anteriormente.