Share via


Datenbankcursor

Ein Datenbankcursor ist ein Objekt auf Datenbankebene, mit dem Sie eine Datenbank mehrmals abfragen können. Sie erhalten konsistente Ergebnisse, auch wenn es Vorgänge gibt oder data-retention parallel zu den Abfragen ausgeführt werdendata-append.

Datenbankcursors sind für zwei wichtige Szenarien konzipiert:

  • Die Möglichkeit, dieselbe Abfrage mehrmals zu wiederholen und die gleichen Ergebnisse zu erhalten, solange die Abfrage "dasselbe Dataset" angibt.

  • Die Möglichkeit, eine Abfrage "genau einmal" auszuführen. Diese Abfrage "sieht" nur die Daten, die von einer vorherigen Abfrage nicht angezeigt wurden, da die Daten damals nicht verfügbar waren. Mit der Abfrage können Sie beispielsweise alle neu eingetroffenen Daten in einer Tabelle durchlaufen, ohne denselben Datensatz zweimal zu verarbeiten oder versehentlich Datensätze zu überspringen.

Der Datenbankcursor wird in der Abfragesprache als skalarer Wert vom Typ stringdargestellt. Der tatsächliche Wert sollte als undurchsichtig betrachtet werden, und es gibt keine andere Unterstützung für einen Vorgang als das Speichern des Werts oder die Verwendung der unten aufgeführten Cursorfunktionen.

Cursorfunktionen

Kusto bietet drei Funktionen, um die beiden oben genannten Szenarien zu implementieren:

  • cursor_current(): Verwenden Sie diese Funktion, um den aktuellen Wert des Datenbankcursors abzurufen. Sie können diesen Wert als Argument für die beiden anderen Funktionen verwenden.

  • cursor_after(rhs:string): Diese spezielle Funktion kann für Tabellendatensätze verwendet werden, für die die IngestionTime-Richtlinie aktiviert ist. Es gibt einen skalaren Wert vom Typ bool zurück, der angibt, ob der Datenbankcursorwert des Datensatzes ingestion_time() nach dem rhs Datenbankcursorwert kommt.

  • cursor_before_or_at(rhs:string): Diese spezielle Funktion kann für die Tabellendatensätze verwendet werden, für die die IngestionTime-Richtlinie aktiviert ist. Es gibt einen skalaren Wert vom Typ bool zurück, der angibt, ob der Datenbankcursorwert des rhs Datensatzes ingestion_time() vor oder am Datenbankcursorwert liegt.

Die beiden Sonderfunktionen (cursor_after und cursor_before_or_at) haben auch einen Nebeneffekt: Wenn sie verwendet werden, gibt Kusto den aktuellen Wert des Datenbankcursors an das @ExtendedProperties Resultset der Abfrage aus. Der Eigenschaftsname für den Cursor ist Cursor, und sein Wert ist ein einzelner string.

Beispiel:

{"Cursor" : "636040929866477946"}

Beschränkungen

Datenbankcursor können nur mit Tabellen verwendet werden, für die die IngestionTime-Richtlinie aktiviert wurde. Jeder Datensatz in einer solchen Tabelle ist dem Wert des Datenbankcursors zugeordnet, der beim Erfassen des Datensatzes wirksam war. Daher kann die funktion ingestion_time() verwendet werden.

Das Datenbankcursorobjekt enthält keinen aussagekräftigen Wert, es sei denn, die Datenbank verfügt über mindestens eine Tabelle mit definierter IngestionTime-Richtlinie . Dieser Wert wird garantiert nach Bedarf durch den Erfassungsverlauf in solche Tabellen und die ausgeführten Abfragen aktualisiert, die auf solche Tabellen verweisen. In anderen Fällen kann sie aktualisiert werden.

Der Erfassungsprozess committ zuerst die Daten, sodass sie für Abfragen verfügbar sind, und weist erst dann jedem Datensatz einen tatsächlichen Cursorwert zu. Wenn Sie versuchen, Daten direkt nach der Erfassung mit einem Datenbankcursor abzufragen, enthalten die Ergebnisse möglicherweise noch nicht die zuletzt hinzugefügten Datensätze, da ihnen der Cursorwert noch nicht zugewiesen wurde. Außerdem kann das wiederholte Abrufen des aktuellen Datenbankcursorwerts denselben Wert zurückgeben, auch wenn die Erfassung dazwischen erfolgt ist, da nur ein Cursorcommit seinen Wert aktualisieren kann.

Das Abfragen einer Tabelle basierend auf Datenbankcursors ist nur dann garantiert, dass sie "funktioniert" (garantiert einmal genau), wenn die Datensätze direkt in dieser Tabelle erfasst werden. Wenn Sie Erweiterungsbefehle verwenden, z. B. move extents.replace/extents, um Daten in die Tabelle zu verschieben, oder wenn Sie die .rename-Tabelle verwenden, wird beim Abfragen dieser Tabelle mithilfe von Datenbankcursors nicht garantiert, dass keine Daten fehlen. Dies liegt daran, dass die Erfassungszeit der Datensätze bei der anfänglichen Erfassung zugewiesen wird und sich während des Vorgangs für Verschiebungsausweitungen nicht ändert. Wenn die Ausdehnungen in die Zieltabelle verschoben werden, ist es daher möglich, dass der Den Datensätzen in diesen Ausdehnungen zugewiesene Cursorwert bereits verarbeitet wurde (und die nächste Abfrage durch den Datenbankcursor die neuen Datensätze verpasst).

Beispiel: Verarbeiten von Datensätzen genau einmal

Verwenden Sie für eine Tabelle Employees mit Schema [Name, Salary]den folgenden Prozess, um kontinuierlich neue Datensätze zu verarbeiten, während sie in der Tabelle erfasst werden:

// [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