Partage via


Curseurs de base de données

S’applique à : ✅Azure Data Explorer

Un curseur de base de données est un objet au niveau de la base de données qui vous permet d’interroger une base de données plusieurs fois. Vous obtenez des résultats cohérents même si des opérations data-append ou data-retention se produisent en parallèle avec les requêtes.

Les curseurs de base de données sont conçus pour traiter deux scénarios importants :

  • Possibilité de répéter la même requête plusieurs fois et d’obtenir les mêmes résultats, tant que la requête indique « même jeu de données ».

  • Possibilité d’effectuer une requête « exactement une seule fois ». Cette requête « voit » uniquement les données qu’une requête précédente ne voyait pas, car les données n’ont pas été disponibles. La requête vous permet d’itérer, par exemple, toutes les données nouvellement arrivées dans une table sans craindre de traiter le même enregistrement deux fois ou d’ignorer les enregistrements par erreur.

Le curseur de base de données est représenté dans le langage de requête sous la forme d’une valeur scalaire de type string. La valeur réelle doit être considérée comme opaque et il n’existe aucune prise en charge d’une opération autre que d’enregistrer sa valeur ou d’utiliser les fonctions de curseur suivantes.

Fonctions de curseur

Kusto fournit trois fonctions pour aider à implémenter les deux scénarios ci-dessus :

  • cursor_current(): utilisez cette fonction pour récupérer la valeur actuelle du curseur de base de données. Vous pouvez utiliser cette valeur comme argument pour les deux autres fonctions.

  • cursor_after(rhs :string): cette fonction spéciale peut être utilisée sur les enregistrements de table dont la stratégie IngestionTime activée. Elle retourne une valeur scalaire de type bool indiquant si la valeur du curseur de base de données ingestion_time() de l’enregistrement est postérieure à la valeur du curseur de base de données rhs.

  • cursor_before_or_at(rhs :string) : cette fonction spéciale peut être utilisée sur les enregistrements de table dont la stratégie IngestionTime est activée. Elle retourne une valeur scalaire de type bool indiquant si la valeur du curseur de base de données ingestion_time() de l’enregistrement est antérieure ou à la valeur du curseur de base de données rhs.

Les deux fonctions spéciales (cursor_after et cursor_before_or_at) ont également un effet secondaire : lorsqu’elles sont utilisées, Kusto émet la valeur actuelle du curseur de base de données au jeu de résultats @ExtendedProperties de la requête. Le nom de propriété du curseur est Cursor, et sa valeur est une seule string.

Par exemple:

{"Cursor" : "636040929866477946"}

Restrictions

Les curseurs de base de données peuvent uniquement être utilisés avec des tables pour lesquelles la stratégie IngestionTime est activée. Chaque enregistrement d’une telle table est associé à la valeur du curseur de base de données qui était en vigueur lorsque l’enregistrement a été ingéré. Par conséquent, la fonction ingestion_time() peut être utilisée.

L’objet curseur de base de données ne contient aucune valeur significative, sauf si la base de données a au moins une table qui a une stratégie IngestionTime définie définie. Cette valeur est garantie de mettre à jour, selon les besoins de l’historique d’ingestion, dans de telles tables et les requêtes exécutées, qui référencent ces tables. Il peut, ou non, être mis à jour dans d’autres cas.

Le processus d’ingestion valide d’abord les données, de sorte qu’elles soient disponibles pour l’interrogation, puis n’attribuent qu’une valeur de curseur réelle à chaque enregistrement. L’interrogation de données immédiatement après l’ingestion à l’aide d’un curseur de base de données peut ne pas incorporer les derniers enregistrements ajoutés, car la valeur du curseur n’a pas encore été affectée. En outre, la récupération répétée de la valeur du curseur de base de données actuelle peut renvoyer la même valeur, même si l’ingestion a été effectuée entre elles, car seule une validation de curseur peut mettre à jour sa valeur.

L’interrogation d’une table basée sur des curseurs de base de données n’est garantie que pour « fonctionner » (en fournissant des garanties exactement une fois) si les enregistrements sont ingérés directement dans cette table. Si vous utilisez des commandes d’étendues, telles que .move extents ou .replace extents pour déplacer des données dans la table, ou si vous utilisez .rename table, l’interrogation de cette table à l’aide de curseurs de base de données n’est pas garantie pour éviter toute absence de données. Cela est dû au fait que le temps d’ingestion des enregistrements est affecté lors de l’ingestion initiale et ne change pas pendant l’opération d’extension de déplacement.

Lorsque les étendues sont déplacées dans la table cible, la valeur du curseur affectée peut déjà avoir été traitée, et la requête suivante par le curseur de base de données manquera les nouveaux enregistrements.

Exemple : Traitement des enregistrements exactement une fois

Pour une table Employees avec le schéma [Name, Salary], pour traiter en permanence de nouveaux enregistrements à mesure qu’ils sont ingérés dans la table, utilisez le processus suivant :

// [Once] Enable the IngestionTime policy on table Employees
.set table Employees policy ingestiontime true

// [Once] Get all the data that the Employees table currently holds 
Employees | where cursor_after('')

// The query above will return the database cursor value in
// the @ExtendedProperties result set. Lets assume that it returns
// the value '636040929866477946'

// [Many] Get all the data that was added to the Employees table
// since the previous query was run using the previously-returned
// database cursor 
Employees | where cursor_after('636040929866477946') // -> 636040929866477950

Employees | where cursor_after('636040929866477950') // -> 636040929866479999

Employees | where cursor_after('636040929866479999') // -> 636040939866479000