Nous utilisons CDC pour capturer les modifications apportées à une table de production. Les lignes modifiées sont exportées vers un entrepôt de données (informatica). Je sais que la colonne __ $ update_mask stocke quelles colonnes ont été mises à jour sous une forme varbinaire. Je sais également que je peux utiliser une variété de fonctions CDC pour découvrir à partir de ce masque quelles étaient ces colonnes.
Ma question est la suivante. Quelqu'un peut-il définir pour moi la logique derrière ce masque afin que nous puissions identifier les colonnes qui ont été changées dans l'entrepôt? Puisque nous traitons en dehors du serveur, nous n'avons pas facilement accès à ces fonctions CDC MSSQL. Je préfère simplement décomposer le masque moi-même en code. Les performances des fonctions cdc du côté SQL sont problématiques pour cette solution.
En bref, j'aimerais identifier manuellement les colonnes modifiées à partir du champ __ $ update_mask.
Mise à jour:
En tant qu'alternative, l'envoi d'une liste lisible par l'homme des colonnes modifiées à l'entrepôt était également acceptable. Nous avons constaté que cela pouvait être effectué avec des performances bien supérieures à notre approche d'origine.
La réponse du CLR à cette question ci-dessous répond à cette alternative et comprend des détails d'interprétation du masque pour les futurs visiteurs. Cependant, la réponse acceptée en utilisant XML PATH est la plus rapide pour le même résultat final.
Réponses:
Et la morale de l'histoire est ... tester, essayer d'autres choses, voir grand, puis petit, supposer toujours qu'il y a une meilleure façon.
Aussi intéressant scientifiquement que ma dernière réponse. J'ai décidé d'essayer une autre approche. Je me suis souvenu que je pouvais concaténer avec l'astuce XML PATH (''). Comme je savais comment obtenir l'ordinal de chaque colonne modifiée à partir de la liste capturée_colonne de la réponse précédente, je pensais que cela valait la peine de tester si la fonction de bit MS fonctionnerait mieux de cette façon pour ce dont nous avions besoin.
C'est beaucoup plus propre que (mais pas aussi amusant que) tout ce CLR, renvoie l'approche au code SQL natif uniquement. Et, roulement de tambour .... renvoie les mêmes résultats en moins d'une seconde . Étant donné que les données de production sont 100 fois plus importantes chaque seconde compte.
Je laisse l'autre réponse à des fins scientifiques - mais pour l'instant, c'est notre bonne réponse.
la source
Ainsi, après quelques recherches, nous avons décidé de continuer à le faire côté SQL avant de passer à l'entrepôt de données. Mais nous adoptons cette approche bien améliorée (basée sur nos besoins et une nouvelle compréhension du fonctionnement du masque).
Nous obtenons une liste des noms de colonnes et leurs positions ordinales avec cette requête. Le retour revient dans un format XML afin que nous puissions passer à SQL CLR.
Nous passons ensuite ce bloc XML en tant que variable et le champ de masque à une fonction CLR qui renvoie une chaîne délimitée par des virgules des colonnes modifiées par le champ binaire _ $ update_mask. Cette fonction clr interroge le champ de masque pour le bit de changement pour chaque colonne de la liste xml, puis renvoie son nom à partir de l'ordinal associé.
Le code c # clr ressemble à ceci: (compilé dans un assembly appelé CDCUtilities)
Et la fonction du CLR comme ceci:
Nous ajoutons ensuite cette liste de colonnes à l'ensemble de lignes et passons à l'entrepôt de données pour analyse. En utilisant la requête et le clr, nous évitons d'avoir à utiliser deux appels de fonction par ligne par changement. Nous pouvons passer directement à la viande avec des résultats personnalisés pour notre instance de capture de changement.
Merci à ce post stackoverflow suggéré par Jon Seigel pour la manière d'interpréter le masque.
D'après notre expérience avec cette approche, nous sommes en mesure d'obtenir une liste de toutes les colonnes modifiées à partir de 10 000 lignes cdc en moins de 3 secondes.
la source