Datenbankcursor
Gilt für: ✅Azure Data Explorer
Ein Datenbankcursor ist ein Objekt auf Datenbankebene, mit dem Sie eine Datenbank mehrmals abfragen können. Sie erhalten konsistente Ergebnisse, auch wenn data-append
oder data-retention
Vorgänge parallel zu den Abfragen ausgeführt werden.
Datenbankcursor sind darauf ausgelegt, zwei wichtige Szenarien zu behandeln:
Die Möglichkeit, dieselbe Abfrage mehrmals zu wiederholen und dieselben Ergebnisse zu erhalten, solange die Abfrage "dieselbe Datenmenge" angibt.
Die Möglichkeit, eine Abfrage "genau einmal" zu erstellen. Diese Abfrage sieht nur die Daten, die eine vorherige Abfrage nicht sehen konnte, da die Daten dann nicht verfügbar waren. Mit der Abfrage können Sie beispielsweise alle neu eingetroffenen Daten in einer Tabelle durchlaufen, ohne befürchten zu müssen, denselben Datensatz zweimal zu verarbeiten oder Datensätze versehentlich zu überspringen.
Der Datenbankcursor wird in der Abfragesprache als skalarer Wert vom Typ string
dargestellt. Der tatsächliche Wert sollte als undurchsichtig betrachtet werden, und es gibt keine Unterstützung für einen anderen Vorgang, als den Wert zu speichern oder die folgenden Cursorfunktionen zu verwenden.
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, die die IngestionTime-Richtlinie aktiviert haben. Er gibt einen skalaren Wert vom Typ
bool
zurück, der angibt, ob deringestion_time()
Datenbankcursorwert des Datensatzes nach demrhs
Datenbankcursorwert liegt.cursor_before_or_at(rhs:string): Diese spezielle Funktion kann für die Tabellendatensätze verwendet werden, die die IngestionTime-Richtlinie aktiviert haben. Er gibt einen skalaren Wert vom Typ
bool
zurück, der angibt, ob deringestion_time()
Datenbankcursorwert des Datensatzes vor oder amrhs
Datenbankcursorwert liegt.
Die beiden speziellen Funktionen (cursor_after
und cursor_before_or_at
) haben ebenfalls 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
.
Zum Beispiel:
{"Cursor" : "636040929866477946"}
Einschränkungen
Datenbankcursor können nur mit Tabellen verwendet werden, für die die IngestionTime-Richtlinie aktiviert ist. Jeder Datensatz in einer solchen Tabelle ist dem Wert des Datenbankcursors zugeordnet, der beim Aufnehmen des Datensatzes wirksam war. Daher kann die ingestion_time()-Funktion verwendet werden.
Das Datenbankcursorobjekt enthält keinen aussagekräftigen Wert, es sei denn, die Datenbank hat mindestens eine Tabelle mit einer IngestionTime-Richtlinie definiert. Dieser Wert wird garantiert aktualisiert, je nach Bedarf durch den Aufnahmeverlauf, in solche Tabellen und die ausgeführten Abfragen, die auf solche Tabellen verweisen. Es kann in anderen Fällen aktualisiert werden oder nicht.
Der Aufnahmevorgang führt zunächst einen Commit für die Daten durch, sodass er für die Abfrage verfügbar ist und jedem Datensatz dann nur einen tatsächlichen Cursorwert zuweist. Das Abfragen nach Daten unmittelbar nach dem Aufnehmen eines Datenbankcursors enthält möglicherweise nicht die zuletzt hinzugefügten Datensätze, da der Cursorwert noch nicht zugewiesen wurde. Außerdem kann das Abrufen des aktuellen Datenbankcursorwerts denselben Wert zurückgeben, auch wenn die Aufnahme dazwischen erfolgt ist, da nur ein Cursor-Commit seinen Wert aktualisieren kann.
Das Abfragen einer Tabelle, die auf Datenbankcursorn basiert, ist nur gewährleistet, dass sie "funktioniert" (die genau einmal garantiert wird), wenn die Datensätze direkt in diese Tabelle aufgenommen werden. Wenn Sie Erweiterungsbefehle verwenden, z. B. .move extents oder .replace extents, um Daten in die Tabelle zu verschieben, oder wenn Sie .rename-Tabelleverwenden, ist das Abfragen dieser Tabelle mit Datenbankcursorn nicht garantiert, um fehlende Daten zu vermeiden. Dies liegt daran, dass die Aufnahmezeit der Datensätze beim anfänglichen Aufnehmen zugewiesen wird und sich während des Verschiebungsausdehnungsvorgangs nicht ändert.
Wenn die Erweiterungen in die Zieltabelle verschoben werden, wurde der zugewiesene Cursorwert möglicherweise bereits verarbeitet, und die nächste Abfrage durch den Datenbankcursor verpasst die neuen Datensätze.
Beispiel: Verarbeiten von Datensätzen genau einmal
Verwenden Sie für eine Tabelle Employees
mit Schema-[Name, Salary]
, um neue Datensätze kontinuierlich zu verarbeiten, während sie in die Tabelle aufgenommen werden, den folgenden Prozess:
// [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