Como impedir deadlocks Columnstore particionados no SELECT

10

Eu tenho três tabelas CCI (Clustered Columnstore Index) no SQL Server 2016. Todas essas CCIs estão no mesmo esquema de particionamento, com base no ID do inquilino. Ultimamente e inconsistentemente, estou obtendo impasses em simples instruções de seleção de junções a essas tabelas. Consulta de exemplo que trava:

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

Mensagem de erro:

A transação (ID do Processo 56) foi bloqueada em recursos genéricos de objetos esperáveis ​​com outro processo e foi escolhida como vítima do conflito. Execute novamente a transação.

Pistas:

  • Se a consulta usar outro índice além do CCI, não haverá conflito.
  • Se eu remover dois dos três filtros de inquilino, ele não entra em conflito.
  • Se eu selecionar os 32 melhores ou menos, não haverá conflito.
  • Se eu adicionar OPTION (MAXDOP 1), não haverá conflito.
  • Posso reproduzir isso na minha réplica embaralhada do PROD, no PROD READ-ONLY Secondary e no próprio PROD.
  • Não consigo reproduzir esse comportamento no DEV ou INT.
  • Ele ainda trava se eu adicionar WITH (NOLOCK) a todas as 3 junções da tabela
  • A consulta entra em conflito. Ele entrará em conflito quando não houver outros processos ativos.
  • Os planos de consulta sem paralelismo não entram em conflito

Xml de impasse aqui

Nossa versão PROD:

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

Como evito impasses nessa consulta?

Cyndi Baker
fonte

Respostas:

8

Como você está no SQL Server 2016, vale ressaltar que há pelo menos uma correção pública de bug para conflitos paralelos que envolvem índices columnstore:

CORRECÇÃO: Um conflito ocorre quando você executa uma consulta paralela em um índice columnstore clusterizado no SQL Server 2016 e 2017

(obrigado Denis Rubashkin por fornecer o link inicialmente)

Este foi lançado como parte do SP1 CU7. Se você não gosta dessa UC, deve tentar. Essa correção também seria incluída no SP2 (qualquer uma das UCs).

Em geral, as duas abordagens para corrigir os conflitos de paralelismo intra-consulta:

  • evitar paralelismo (ajustando a consulta para que não fique paralela, usando uma MAXDOPdica etc.) - isso é abordado na outra resposta de Thomas Costers
  • aplique as atualizações mais recentes do service pack / cumulativas ao SQL Server
Josh Darnell
fonte
2

Você verificou o seguinte blog em Deadlocks de thread paralelo intra-consulta

O SyncPointrecurso indica o uso de um evento de troca, se não me engano.
Olhando para os participantes do seu impasse, você pode ver que todos são provenientes do mesmo spid (55) e lote (0), mas estão usando threads diferentes. Isso indica que todos fazem parte da mesma consulta paralela e é confirmado pelo fato de que você não recebe nenhum conflito sempre que executa a consulta MAXDOP 1. No caso de deadlocks de encadeamentos paralelos entre consultas, os encadeamentos de uma única consulta acabam bloqueando um ao outro, aguardando objetos de sincronização, SyncPoints no seu caso.

Na última vez em que testemunhei esse tipo de comportamento, pude otimizar ainda mais a consulta e, assim, impedir que ela usasse um plano de execução paralelo. Eu suspeito que você fez a mesma coisa limitando o conjunto de resultados a 32 registros ou usando um índice diferente.
Outra opção seria adicionar MAXDOP 1à sua consulta, embora não seja um grande fã dessa opção.

Mas antes de brincar com essas duas opções, verifique primeiro se você está no SP / CU mais recente.

Thomas Costers
fonte