Dela via


Databasmarkörer

En databasmarkör är ett objekt på databasnivå som gör att du kan köra frågor mot en databas flera gånger. Du får konsekventa resultat även om det finns data-append eller data-retention åtgärder som utförs parallellt med frågorna.

Databasmarkörer är utformade för att hantera två viktiga scenarier:

  • Möjligheten att upprepa samma fråga flera gånger och få samma resultat, förutsatt att frågan anger "samma datauppsättning".

  • Möjligheten att skapa en "exakt en gång"-fråga. Den här frågan "ser" bara de data som en tidigare fråga inte såg, eftersom data inte var tillgängliga då. Med frågan kan du till exempel iterera genom alla nyligen ankomna data i en tabell utan rädsla för att bearbeta samma post två gånger eller hoppa över poster av misstag.

Databasmarkören representeras i frågespråket som ett skalärt värde av typen string. Det faktiska värdet bör betraktas som ogenomskinlig och det finns inget stöd för någon annan åtgärd än att spara dess värde eller använda markörfunktionerna som anges nedan.

Markörfunktioner

Kusto har tre funktioner som hjälper dig att implementera de två scenarierna ovan:

  • cursor_current(): Använd den här funktionen för att hämta databasmarkörens aktuella värde. Du kan använda det här värdet som ett argument för de två andra funktionerna.

  • cursor_after(rhs:string): Den här specialfunktionen kan användas för tabellposter som har IngestionTime-principen aktiverad. Den returnerar ett skalärt värde av typen bool som anger om postens databasmarkörvärde kommer efter rhs databasens ingestion_time() markörvärde.

  • cursor_before_or_at(rhs:string): Den här specialfunktionen kan användas för de tabellposter som har IngestionTime-principen aktiverad. Den returnerar ett skalärt värde av typen bool som anger om postens ingestion_time() databasmarkörvärde kommer före eller vid rhs databasmarkörvärdet.

De två specialfunktionerna (cursor_after och cursor_before_or_at) har också en bieffekt: När de används genererar Kusto det aktuella värdet för databasmarkören till @ExtendedProperties resultatuppsättningen för frågan. Markörens egenskapsnamn är Cursoroch dess värde är en enda string.

Exempel:

{"Cursor" : "636040929866477946"}

Begränsningar

Databasmarkörer kan bara användas med tabeller där IngestionTime-principen har aktiverats. Varje post i en sådan tabell är associerad med värdet för databasmarkören som användes när posten matades in. Därför kan funktionen ingestion_time() användas.

Databasmarkörobjektet innehåller inget meningsfullt värde om inte databasen har minst en tabell som har en IngestionTime-princip definierad. Det här värdet uppdateras garanterat efter behov av inmatningshistoriken till sådana tabeller och de frågor som körs, som refererar till sådana tabeller. Det kan, eller kanske inte, uppdateras i andra fall.

Inmatningsprocessen checkar först in data, så att de är tillgängliga för frågor och tilldelar först sedan ett faktiskt markörvärde till varje post. Om du försöker fråga efter data omedelbart efter att inmatningen har slutförts med hjälp av en databasmarkör kanske resultatet ännu inte innehåller de sista posterna som lagts till, eftersom de ännu inte har tilldelats markörens värde. Om du hämtar det aktuella databasmarkörvärdet upprepade gånger kan det returnera samma värde, även om inmatningen gjordes däremellan, eftersom endast en markörincheckning kan uppdatera dess värde.

Att köra frågor mot en tabell baserat på databasmarkörer garanteras bara "fungera" (ge garantier exakt en gång) om posterna matas in direkt i tabellen. Om du använder utrymmeskommandon, till exempel flytta extents.replace-utrymmen/ för att flytta data till tabellen, eller om du använder .rename-tabellen, är det inte säkert att du inte missar några data om du kör frågor mot den här tabellen med databasmarkörer. Det beror på att inmatningstiden för posterna tilldelas när de först matas in och inte ändras under flyttomfångsåtgärden. När utrymmena flyttas till måltabellen är det därför möjligt att markörens värde som tilldelats posterna i dessa utrymmen redan har bearbetats (och nästa fråga med databasmarkören missar de nya posterna).

Exempel: Bearbeta poster exakt en gång

För en tabell Employees med schema [Name, Salary]använder du följande process för att kontinuerligt bearbeta nya poster när de matas in i tabellen:

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