データベース カーソル

データベース カーソルは、データベースに対して複数回クエリを実行できるデータベース レベルのオブジェクトです。 または 操作がクエリと並行して実行されているdata-appenddata-retention場合でも、一貫した結果が得られます。

データベース カーソルは、次の 2 つの重要なシナリオに対応するように設計されています。

  • クエリが "同じデータ セット" を示している限り、同じクエリを複数回繰り返し、同じ結果を取得する機能。

  • "1 回だけ" クエリを作成する機能。 このクエリでは、以前のクエリで表示されなかったデータのみを "表示" します。これは、その時点ではデータが使用できなかったためです。 このクエリを使用すると、たとえば、同じレコードを 2 回処理したり、誤ってレコードをスキップしたりする恐れなく、テーブル内の新しく到着したデータを反復処理できます。

データベース カーソルは、クエリ言語で string 型のスカラー値として表されます。 実際の値は非透過的と見なす必要があります。その値を保存したり、以下に示すカーソル関数を使用したりする以外の操作はサポートされていません。

カーソル関数

Kusto には、上記の 2 つのシナリオの実装に役立つ 3 つの関数が含まれています。

  • cursor_current(): この関数を使用して、データベース カーソルの現在の値を取得します。 この値は、他の 2 つの関数の引数として使用できます。

  • cursor_after(rhs:string): この特殊な関数は、IngestionTime ポリシーが有効になっているテーブル レコードで使用できます。 レコードの ingestion_time() データベース カーソル値が rhs データベース カーソル値の後に来るかどうかを示す、bool 型のスカラー値を返します。

  • cursor_before_or_at(rhs:string): この特殊な関数は、IngestionTime ポリシーが有効になっているテーブル レコードで使用できます。 レコードの ingestion_time() データベース カーソル値が rhs データベース カーソル値の前に来るかどうかを示す、bool 型のスカラー値を返します。

2 つの特殊な関数 (cursor_aftercursor_before_or_at) には副作用もあります。使用すると、Kusto はデータベース カーソルの現在の値をクエリの @ExtendedProperties 結果セットに出力します。 カーソルのプロパティ名は Cursor で、その値は 1 つの string です。

次に例を示します。

{"Cursor" : "636040929866477946"}

制限

データベース カーソルは、IngestionTime ポリシーが有効になっているテーブルでのみ使用できます。 このようなテーブル内の各レコードは、レコードが取り込まれたときに有効だったデータベース カーソルの値に関連付けられます。 そのため、ingestion_time() 関数を使用できます。

IngestionTime ポリシーが定義されているテーブルがデータベースに少なくとも 1 つある場合を除いて、データベース カーソル オブジェクトは意味のある値を保持しません。 この値は、インジェスト履歴によって必要に応じて、そうしたテーブルと、そうしたテーブルを参照するクエリに更新されることが保証されます。 他の場合は、更新される場合と更新されない場合があります。

インジェスト プロセスは、クエリで使用できるように最初にデータをコミットし、その後、実際のカーソル値を各レコードに割り当てます。 データベース カーソルを使用してインジェストの完了直後にデータのクエリを実行しようとすると、カーソル値がまだ割り当てられていないため、最後に追加されたレコードが結果に組み込まれない可能性があります。 また、データベース カーソル値を更新できるのはカーソル コミットだけであるため、現在のデータベース カーソル値を繰り返し取得すると、その間にインジェストが行われた場合でも、同じ値が返される可能性があります。

データベース カーソルに基づいてテーブルのクエリを実行すると、レコードがそのテーブルに直接取り込まれた場合にのみ、"動作" が保証されます (厳密に 1 回の保証が提供されます)。 extents コマンド (extents.replace/ エクステントを移動してテーブルにデータを移動する場合など) を使用している場合、または .rename テーブルを使用している場合は、データベース カーソルを使用してこのテーブルに対してクエリを実行しても、データが見逃されないことは保証されません。 これは、レコードのインジェスト時間は最初に取り込まれたときに割り当てられ、移動エクステント操作中に変更されないためです。 したがって、エクステントをターゲット テーブルに移動すると、これらのエクステント内のレコードに割り当てられたカーソル値が既に処理されている可能性があります (データベース カーソルによる次のクエリでは新しいレコードが欠落します)。

例: レコードを 1 回だけ処理する

スキーマ [Name, Salary] を持つテーブル Employees で、テーブルに取り込まれた新しいレコードを継続的に処理するには、次のプロセスを使用します。

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