Cómo evitar bloqueos de almacenes de columnas particionados en SELECT

10

Tengo tres tablas de índice de almacén de columnas en clúster (CCI) en SQL Server 2016. Todas estas CCI están en el mismo esquema de partición, basado en la identificación del inquilino. Últimamente, e inconsistentemente, estoy llegando a puntos muertos en declaraciones simples de selección de uniones a estas tablas. Ejemplo de consulta que interbloquea:

SELECT  TOP 33 r.tenantid
FROM    Table_r r
        INNER JOIN Table_cm cm ON r.MyKey=cm.MyKey 
        INNER JOIN Table_pe pe ON r.MyKey=pe.MyKey 
WHERE   r.TenantId = 69
        AND pe.TenantId = 69
        AND cm.TenantId = 69

Mensaje de error:

La transacción (ID de proceso 56) se bloqueó en recursos genéricos de objetos esperables con otro proceso y se ha elegido como víctima de bloqueo. Vuelva a ejecutar la transacción.

Pistas:

  • Si la consulta usa otro índice además del CCI, no tiene punto muerto.
  • Si elimino dos de los tres filtros de tenantid, no se bloquea.
  • Si SELECCIONO el top 32 o inferior, no se bloquea.
  • Si agrego OPCIÓN (MAXDOP 1) no se bloquea.
  • Puedo reprobar esto en mi réplica PROD revuelta, PROD READ-ONLY Secondary y PROD en sí.
  • No puedo reprochar este comportamiento en DEV o INT.
  • Todavía se interrumpe si agrego WITH (NOLOCK) a las 3 combinaciones de tabla
  • La consulta se interrumpe. Se bloqueará cuando no haya otros procesos activos.
  • Los planes de consulta sin paralelismo no se estancan

Deadlock xml aquí

Nuestra versión PROD:

Microsoft SQL Server 2016 (SP2-CU5) (KB4475776) - 13.0.5264.1 (X64) 10 de enero de 2019 18:51:38 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) en Windows Server 2012 R2 Standard 6.3 (Build 9600 :) (Hipervisor)

¿Cómo evito puntos muertos en esta consulta?

Cyndi Baker
fuente

Respuestas:

8

Dado que está en SQL Server 2016, vale la pena mencionar que hay al menos una corrección de error pública para puntos muertos paralelos que involucran índices de almacén de columnas:

REVISIÓN: se produce un punto muerto cuando ejecuta una consulta paralela en un índice de almacén de columnas agrupado en SQL Server 2016 y 2017

(gracias a Denis Rubashkin por proporcionar el enlace inicialmente)

Esto fue lanzado como parte de SP1 CU7. Si no estás a la altura de esa CU, deberías darle una oportunidad. Esta solución también se incluiría en SP2 (cualquiera de las CU).

En general, los dos enfoques para corregir puntos muertos de paralelismo intraconsulta:

  • evitar el paralelismo (ajustando la consulta para que no sea paralela, usando una MAXDOPpista, etc.): esto está cubierto en la otra respuesta de Thomas Costers
  • aplicar el último service pack / actualizaciones acumulativas a SQL Server
Josh Darnell
fuente
2

¿Has consultado el siguiente blog sobre puntos muertos de hilo paralelo de consultas internas?

El SyncPointrecurso indica el uso de un evento de intercambio si no me equivoco.
Al observar a los participantes de su punto muerto, puede ver que todos provienen del mismo spid (55) y lote (0), pero están utilizando diferentes hilos. Esto indica que todos forman parte de la misma consulta paralela y se confirma por el hecho de que no recibe ningún punto muerto cada vez que ejecuta la consulta MAXDOP 1. En el caso de interbloqueos de subprocesos paralelos de consultas internas, los subprocesos de una sola consulta terminarán interbloqueándose entre sí esperando objetos de sincronización, SyncPoints en su caso.

La última vez que presencié este tipo de comportamiento, pude optimizar aún más la consulta y evitar así que la consulta utilice un plan de ejecución paralelo. Sospecho que hizo lo mismo al limitar su conjunto de resultados a 32 registros o al usar un índice diferente.
Otra opción sería agregar MAXDOP 1a su consulta, aunque no es un gran admirador de esta opción.

Pero antes de jugar con esas dos opciones, primero verifique si tiene la última SP / CU.

Thomas Costers
fuente