Compartir a través de


Cursores de base de datos

Se aplica a: ✅ de Azure Data Explorer

Un cursor de base de datos es un objeto de nivel de base de datos que permite consultar una base de datos varias veces. Obtiene resultados coherentes incluso si hay data-append o data-retention operaciones que se producen en paralelo con las consultas.

Los cursores de base de datos están diseñados para abordar dos escenarios importantes:

  • La capacidad de repetir la misma consulta varias veces y obtener los mismos resultados, siempre y cuando la consulta indique "el mismo conjunto de datos".

  • La capacidad de realizar una consulta "exactamente una vez". Esta consulta solo "ve" los datos que no vio una consulta anterior, ya que los datos no están disponibles entonces. La consulta le permite iterar, por ejemplo, a través de todos los datos recién llegados de una tabla sin miedo a procesar el mismo registro dos veces o omitir registros por error.

El cursor de base de datos se representa en el lenguaje de consulta como un valor escalar de tipo string. El valor real debe considerarse opaco y no hay compatibilidad con ninguna operación que no sea para guardar su valor o usar las siguientes funciones de cursor.

Funciones de cursor

Kusto proporciona tres funciones para ayudar a implementar los dos escenarios anteriores:

  • cursor_current(): use esta función para recuperar el valor actual del cursor de base de datos. Puede usar este valor como argumento para las otras dos funciones.

  • cursor_after(rhs:string): esta función especial se puede usar en los registros de tabla que tienen habilitada la directiva ingestionTime de . Devuelve un valor escalar de tipo bool que indica si el valor del cursor de base de datos ingestion_time() del registro viene después del valor del cursor de base de datos rhs.

  • cursor_before_or_at(rhs:string): esta función especial se puede usar en los registros de tabla que tienen habilitada la directiva ingestionTime de . Devuelve un valor escalar de tipo bool que indica si el valor del cursor de base de datos ingestion_time() del registro viene antes o en el valor del cursor de base de datos rhs.

Las dos funciones especiales (cursor_after y cursor_before_or_at) también tienen un efecto secundario: Cuando se usan, Kusto emite el valor actual del cursor de base de datos al conjunto de resultados @ExtendedProperties de la consulta. El nombre de propiedad del cursor es Cursory su valor es un solo string.

Por ejemplo:

{"Cursor" : "636040929866477946"}

Restricciones

Los cursores de base de datos solo se pueden usar con tablas para las que está habilitada la directiva ingestionTime de . Cada registro de esta tabla está asociado al valor del cursor de base de datos que estaba en vigor cuando se ingerió el registro. Por lo tanto, se puede usar la función ingestion_time().

El objeto de cursor de base de datos no contiene ningún valor significativo a menos que la base de datos tenga al menos una tabla que tenga una directiva ingestionTime de definida. Este valor se garantiza que actualice, según sea necesario, en el historial de ingesta, en estas tablas y las consultas ejecutadas, que hacen referencia a dichas tablas. Es posible que, o no, se actualice en otros casos.

El proceso de ingesta confirma primero los datos, de modo que esté disponible para realizar consultas y solo asigna un valor de cursor real a cada registro. La consulta de datos inmediatamente después de la ingesta mediante un cursor de base de datos podría no incorporar los últimos registros agregados porque aún no se asignó el valor del cursor. Además, recuperar el valor actual del cursor de base de datos repetidamente podría devolver el mismo valor, incluso si la ingesta se realizó entre sí, ya que solo una confirmación del cursor puede actualizar su valor.

La consulta de una tabla basada en cursores de base de datos solo se garantiza que "funcione" (proporcionando garantías exactamente una vez) si los registros se ingieren directamente en esa tabla. Si usa comandos de extensiones, como .move extensiones o .replace extensiones para mover datos a la tabla o si usa tabla .rename, no se garantiza que consulte esta tabla mediante cursores de base de datos para evitar que falten datos. Esto se debe a que el tiempo de ingesta de los registros se asigna cuando se ingiere inicialmente y no cambia durante la operación de extensión de movimiento.

Cuando las extensiones se mueven a la tabla de destino, es posible que el valor del cursor asignado ya se haya procesado y la siguiente consulta del cursor de base de datos perderá los nuevos registros.

Ejemplo: Procesamiento de registros exactamente una vez

Para una tabla Employees con el esquema [Name, Salary], para procesar continuamente nuevos registros a medida que se ingieren en la tabla, use el siguiente proceso:

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