Estamos usando o CDC para capturar as alterações feitas em uma tabela de produção. As linhas alteradas estão sendo exportadas para um data warehouse (informatica). Eu sei que a coluna __$update_mask armazena quais colunas foram atualizadas em um formulário varbinary. Também sei que posso usar uma variedade de funções CDC para descobrir a partir dessa máscara quais eram essas colunas.
Minha pergunta é esta. Alguém pode me definir a lógica dessa máscara para que possamos identificar as colunas que foram trocadas no armazém? Como estamos processando fora do servidor, não temos acesso fácil a essas funções MSSQL CDC. Prefiro apenas quebrar a máscara sozinho no código. O desempenho das funções cdc no final do SQL é problemático para esta solução.
Resumindo, gostaria de identificar manualmente as colunas alteradas no campo __$update_mask.
Atualizar:
Como alternativa, o envio de uma lista legível por humanos de colunas alteradas para o depósito também era aceitável. Descobrimos que isso poderia ser executado com desempenho muito maior do que nossa abordagem original.
A resposta do CLR para esta pergunta abaixo atende a esta alternativa e inclui detalhes de interpretação da máscara para futuros visitantes. No entanto, a resposta aceita usando XML PATH é a mais rápida para o mesmo resultado final.
E a moral da história é... teste, tente outras coisas, pense grande, depois pequeno, sempre assuma que existe uma maneira melhor.
Tão cientificamente interessante quanto foi minha última resposta. Eu decidi tentar uma outra abordagem. Lembrei que poderia concatenar com o truque XML PATH(''). Como eu sabia como obter o ordinal de cada coluna alterada da lista capture_column da resposta anterior, pensei que valeria a pena testar se a função de bit MS funcionaria melhor dessa maneira para o que precisávamos.
É muito mais limpo do que (embora não tão divertido quanto) todo aquele CLR, retorna a abordagem de volta apenas ao código SQL nativo. E rufar de tambores... retorna os mesmos resultados em menos de um segundo . Como os dados de produção são 100 vezes maiores, cada segundo conta.
Estou deixando a outra resposta para fins científicos - mas, por enquanto, esta é a nossa resposta correta.
Então, depois de alguma pesquisa, decidimos ainda fazer isso no lado do SQL antes de passar para o data warehouse. Mas estamos adotando essa abordagem muito aprimorada (com base em nossas necessidades e em uma nova compreensão de como a máscara funciona).
Obtemos uma lista dos nomes das colunas e suas posições ordinais com esta consulta. O retorno volta em um formato XML para que possamos passar para o SQL CLR.
Em seguida, passamos esse bloco XML como uma variável e o campo de máscara para uma função CLR que retorna uma string delimitada por vírgula das colunas que foram alteradas pelo campo binário _$update_mask. Essa função clr interroga o campo de máscara para alterar o bit de cada coluna na lista xml e, em seguida, retorna seu nome do ordinal relacionado.
O código c# clr se parece com isso: (compilado em um assembly chamado CDCUtilities)
E a função para o CLR assim:
Em seguida, anexamos essa lista de colunas ao conjunto de linhas e passamos para o data warehouse para análise. Ao usar a consulta e o clr, evitamos ter que usar duas chamadas de função por linha por alteração. Podemos ir direto ao ponto com resultados personalizados para nossa instância de captura de alterações.
Obrigado a esta postagem stackoverflow sugerida por Jon Seigel pela maneira de interpretar mask.
Em nossa experiência com essa abordagem, conseguimos obter uma lista de todas as colunas alteradas de 10 mil linhas cdc em menos de 3 segundos.