Share via


Curseurs de base de données

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 s’il existe data-append ou data-retention des opérations se produisent en parallèle avec les requêtes.

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

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

  • Possibilité d’effectuer une requête « exactement une fois ». Cette requête « voit » uniquement les données qu’une requête précédente ne voyait pas, car les données n’étaient pas disponibles à ce stade. La requête vous permet d’itérer, par exemple, à travers toutes les données nouvellement arrivées dans une table sans craindre de traiter deux fois le même enregistrement 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 aucune opération n’est prise en charge, sauf pour enregistrer sa valeur ou utiliser les fonctions de curseur indiquées ci-dessous.

Fonctions 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 sur ant la stratégie IngestionTime activée. Il retourne une valeur scalaire de type bool indiquant si la valeur du curseur de base de données de ingestion_time() l’enregistrement vient après la valeur du rhs curseur de base de données.

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

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 vers le @ExtendedProperties jeu de résultats de la requête. Le nom de propriété du curseur est Cursor, et sa valeur est un seul string.

Par exemple :

{"Cursor" : "636040929866477946"}

Restrictions

Les curseurs de base de données ne peuvent être utilisés qu’avec des tables pour lesquelles la stratégie IngestionTime a été activée. Chaque enregistrement d’une telle table est associé à la valeur du curseur de base de données qui était en vigueur lors de l’ingestion de l’enregistrement. 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 avec une stratégie IngestionTime définie. Cette valeur est garantie pour être mise à jour, en fonction des besoins de l’historique d’ingestion, dans ces 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, afin qu’elles soient disponibles pour l’interrogation, puis affecte ensuite une valeur de curseur réelle à chaque enregistrement. Si vous tentez d’interroger des données immédiatement après la fin de l’ingestion à l’aide d’un curseur de base de données, les résultats peuvent ne pas encore incorporer les derniers enregistrements ajoutés, car la valeur du curseur ne leur a pas encore été attribuée. En outre, la récupération répétée de la valeur actuelle du curseur de base de données peut renvoyer la même valeur, même si l’ingestion a été effectuée entre les deux, car seule une validation de curseur peut mettre à jour sa valeur.

L’interrogation d’une table en fonction des curseurs de base de données est garantie uniquement 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 déplacer des étendues.remplacer/les étendues pour déplacer des données dans la table, ou si vous utilisez la table .rename, l’interrogation de cette table à l’aide de curseurs de base de données n’est pas garantie de ne manquer aucune donnée. En effet, le temps d’ingestion des enregistrements est attribué lors de l’ingestion initiale et ne change pas pendant l’opération de déplacement des étendues. Par conséquent, lorsque les étendues sont déplacées dans la table cible, il est possible que la valeur de curseur affectée aux enregistrements dans ces étendues ait déjà été traitée (et que la requête suivante par curseur de base de données manque les nouveaux enregistrements).

Exemple : traitement des enregistrements une seule fois

Pour une table Employees avec un schéma [Name, Salary], pour traiter en continu les 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