Udostępnij za pośrednictwem


Kursory bazy danych

Dotyczy: azure Data Explorer

Kursor bazy danych jest obiektem na poziomie bazy danych, który umożliwia wielokrotne wykonywanie zapytań względem bazy danych. Uzyskujesz spójne wyniki, nawet jeśli istnieją operacje data-append lub data-retention wykonywane równolegle z zapytaniami.

Kursory bazy danych są przeznaczone do rozwiązywania dwóch ważnych scenariuszy:

  • Możliwość wielokrotnego powtarzania tego samego zapytania i uzyskiwania tych samych wyników, o ile zapytanie wskazuje "ten sam zestaw danych".

  • Możliwość tworzenia zapytania "dokładnie raz". To zapytanie "widzi" tylko dane, których poprzednie zapytanie nie widziało, ponieważ dane nie były wówczas dostępne. Zapytanie umożliwia iterowanie, na przykład przez wszystkie nowo przybyłe dane w tabeli bez obawy o przetwarzanie tego samego rekordu dwa razy lub pomijanie rekordów przez pomyłkę.

Kursor bazy danych jest reprezentowany w języku zapytań jako wartość skalarna typu string. Wartość rzeczywista powinna być uważana za nieprzezroczystą i nie ma obsługi żadnej operacji innej niż zapisanie jej wartości lub użycie następujących funkcji kursora.

Funkcje kursora

Usługa Kusto udostępnia trzy funkcje ułatwiające zaimplementowanie dwóch powyższych scenariuszy:

  • cursor_current(): użyj tej funkcji, aby pobrać bieżącą wartość kursora bazy danych. Tej wartości można użyć jako argumentu do dwóch innych funkcji.

  • cursor_after(rhs:string): tej specjalnej funkcji można używać w rekordach tabeli z włączonymi zasadami IngestionTime. Zwraca wartość skalarną typu bool wskazującą, czy wartość kursora bazy danych ingestion_time() rekordu pochodzi po wartości kursora bazy danych rhs.

  • cursor_before_or_at(rhs:string): tej specjalnej funkcji można używać w rekordach tabeli z włączonymi zasadami IngestionTime. Zwraca wartość skalarną typu bool wskazującą, czy wartość kursora bazy danych ingestion_time() rekordu jest wcześniejsza, czy na rhs wartości kursora bazy danych.

Dwie specjalne funkcje (cursor_after i cursor_before_or_at) również mają efekt uboczny: Gdy są używane, Usługa Kusto emituje bieżącą wartość kursora bazy danych do zestawu wyników @ExtendedProperties zapytania. Nazwa właściwości kursora jest Cursor, a jego wartość jest jedną string.

Na przykład:

{"Cursor" : "636040929866477946"}

Ograniczenia

Kursory bazy danych mogą być używane tylko z tabelami, dla których włączono zasady IngestionTime. Każdy rekord w takiej tabeli jest skojarzony z wartością kursora bazy danych, który obowiązywał podczas pozyskiwania rekordu. W związku z tym można użyć funkcji ingestion_time().

Obiekt kursora bazy danych nie zawiera znaczącej wartości, chyba że baza danych ma co najmniej jedną tabelę z zdefiniowaną zasad IngestionTime. Ta wartość jest gwarantowana do zaktualizowania, zgodnie z potrzebami w historii pozyskiwania, do takich tabel i uruchomionych zapytań, które odwołują się do takich tabel. Może być aktualizowany w innych przypadkach lub nie.

Proces pozyskiwania najpierw zatwierdza dane, tak aby był dostępny do wykonywania zapytań, a następnie przypisuje rzeczywistą wartość kursora do każdego rekordu. Wykonywanie zapytań o dane bezpośrednio po pozyskaniu przy użyciu kursora bazy danych może nie uwzględniać dodanych ostatnich rekordów, ponieważ wartość kursora nie została jeszcze przypisana. Ponadto pobieranie bieżącej wartości kursora bazy danych może wielokrotnie zwracać tę samą wartość, nawet jeśli pozyskiwanie zostało wykonane między, ponieważ tylko zatwierdzenie kursora może zaktualizować jego wartość.

Wykonywanie zapytań względem tabeli na podstawie kursorów bazy danych gwarantuje jedynie "pracę" (zapewniając dokładnie jednokrotne gwarancje), jeśli rekordy są pozyskiwane bezpośrednio do tej tabeli. Jeśli używasz poleceń zakresów, takich jak .move extents lub .replace extents, aby przenieść dane do tabeli, lub jeśli używasz .rename tabeli, wykonywanie zapytań względem tej tabeli przy użyciu kursorów bazy danych nie ma gwarancji, aby uniknąć braku żadnych danych. Dzieje się tak, ponieważ czas pozyskiwania rekordów jest przypisywany podczas początkowego pozyskiwania i nie zmienia się podczas operacji przenoszenia.

Gdy zakresy zostaną przeniesione do tabeli docelowej, przypisana wartość kursora mogła już zostać przetworzona, a następne zapytanie przez kursor bazy danych przegapi nowe rekordy.

Przykład: Przetwarzanie rekordów dokładnie raz

W przypadku tabeli Employees ze schematem [Name, Salary], aby stale przetwarzać nowe rekordy podczas pozyskiwania ich do tabeli, użyj następującego procesu:

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