Cursori di database

Un cursore di database è un oggetto a livello di database che consente di eseguire più volte query su un database. Si ottengono risultati coerenti anche se sono data-append presenti operazioni o data-retention in parallelo con le query.

I cursori del database sono progettati per affrontare due scenari importanti:

  • Possibilità di ripetere la stessa query più volte e ottenere gli stessi risultati, purché la query indichi "stesso set di dati".

  • Possibilità di eseguire una query "esattamente una volta". Questa query visualizza solo i dati non visualizzati da una query precedente, perché i dati non erano disponibili. La query consente, ad esempio, di scorrere tutti i dati appena arrivati in una tabella senza timore di elaborare lo stesso record due volte o ignorare i record per errore.

Il cursore del database è rappresentato nel linguaggio di query come valore scalare di tipo string. Il valore effettivo deve essere considerato opaco e non è disponibile alcun supporto per alcuna operazione diversa da salvare il valore o usare le funzioni cursori indicate di seguito.

Funzioni per i cursori

Kusto offre tre funzioni che consentono di implementare i due scenari precedenti:

  • cursor_current(): usare questa funzione per recuperare il valore corrente del cursore del database. È possibile usare questo valore come argomento per le due altre funzioni.

  • cursor_after(rhs:string): questa funzione speciale può essere usata nei record di tabella in cui è abilitato il criterio IngestionTime . Restituisce un valore scalare di tipo bool che indica se il valore del cursore del database del record viene restituito dopo il valore del cursore del ingestion_time()rhs database.

  • cursor_before_or_at(rhs:string): questa funzione speciale può essere usata nei record di tabella in cui è abilitato il criterio IngestionTime . Restituisce un valore scalare di tipo bool che indica se il valore del cursore del database del ingestion_time() record è precedente o al valore del cursore del rhs database.

Le due funzioni speciali (cursor_after e cursor_before_or_at) hanno anche un effetto collaterale: quando vengono usate, Kusto genererà il valore corrente del cursore del database al @ExtendedProperties set di risultati della query. Il nome della proprietà per il cursore è Cursore il relativo valore è un singolo stringoggetto .

Ad esempio:

{"Cursor" : "636040929866477946"}

Restrizioni

I cursori di database possono essere usati solo con le tabelle per cui è stato abilitato il criterio IngestionTime . Ogni record in una tabella di questo tipo è associato al valore del cursore di database attivo al momento dell'inserimento del record. Di conseguenza, è possibile usare la funzione ingestion_time().

L'oggetto cursore del database non contiene alcun valore significativo, a meno che il database non disponga di almeno una tabella con criteri Di inserimentoTime definiti. Questo valore viene sicuramente aggiornato, in base alle esigenze della cronologia di inserimento, in tali tabelle e nelle query eseguite, che fanno riferimento a tali tabelle. Potrebbe, o meno, essere aggiornato in altri casi.

Il processo di inserimento esegue innanzitutto il commit dei dati, in modo che sia disponibile per l'esecuzione di query e quindi assegna un valore di cursore effettivo a ogni record. Se si tenta di eseguire una query per i dati immediatamente dopo il completamento dell'inserimento usando un cursore di database, i risultati potrebbero non incorporare ancora gli ultimi record aggiunti, perché non sono ancora stati assegnati al valore del cursore. Inoltre, il recupero ripetuto del valore del cursore del database corrente potrebbe restituire lo stesso valore, anche se l'inserimento è stato eseguito tra, perché solo un commit del cursore può aggiornarne il valore.

L'esecuzione di query su una tabella basata su cursori di database è garantita solo per il "funzionamento" (fornendo garanzie di tipo exactly-once) se i record vengono inseriti direttamente in tale tabella. Se si usano comandi extent, ad esempio move extents.replace/extents per spostare i dati nella tabella o se si usa la tabella con estensione rename, non è garantito che non si verifichino errori di dati per l'esecuzione di query su questa tabella usando i cursori del database. Ciò è dovuto al fatto che il tempo di inserimento dei record viene assegnato all'inserimento iniziale e non cambia durante l'operazione degli extent di spostamento. Pertanto, quando gli extent vengono spostati nella tabella di destinazione, è possibile che il valore del cursore assegnato ai record in questi extent sia già stato elaborato (e la query successiva eseguita dal cursore del database perderà i nuovi record).

Esempio: Elaborazione di record una sola volta

Per una tabella Employees con schema [Name, Salary], per elaborare continuamente nuovi record durante l'inserimento nella tabella, usare il processo seguente:

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