Partilhar via


Cursores da base de dados

Aplica-se a: ✅Azure Data Explorer

Um cursor de banco de dados é um objeto no nível de banco de dados que permite consultar um banco de dados várias vezes. Você obtém resultados consistentes mesmo se houver data-append ou data-retention operações acontecendo em paralelo com as consultas.

Os cursores de banco de dados são projetados para abordar dois cenários importantes:

  • A capacidade de repetir a mesma consulta várias vezes e obter os mesmos resultados, desde que a consulta indique "mesmo conjunto de dados".

  • A capacidade de fazer uma consulta "exatamente uma vez". Esta consulta apenas "vê" os dados que uma consulta anterior não viu, porque os dados não estavam disponíveis na altura. A consulta permite que você itere, por exemplo, através de todos os dados recém-chegados em uma tabela sem medo de processar o mesmo registro duas vezes ou pular registros por engano.

O cursor do banco de dados é representado na linguagem de consulta como um valor escalar do tipo string. O valor real deve ser considerado opaco e não há suporte para qualquer operação além de salvar seu valor ou usar as seguintes funções de cursor.

Funções do cursor

Kusto fornece três funções para ajudar a implementar os dois cenários acima:

  • cursor_current(): Use esta função para recuperar o valor atual do cursor do banco de dados. Você pode usar esse valor como um argumento para as duas outras funções.

  • cursor_after(rhs:string): Esta função especial pode ser usada em registros de tabela que tenham a política IngestionTime habilitada. Ele retorna um valor escalar do tipo bool indicando se o valor do cursor do banco de dados ingestion_time() do registro vem após o valor do cursor do banco de dados rhs.

  • cursor_before_or_at(rhs:string): Esta função especial pode ser usada nos registros de tabela que têm a política IngestionTime habilitada. Ele retorna um valor escalar do tipo bool indicando se o valor do cursor do banco de dados ingestion_time() do registro vem antes ou no valor do cursor do banco de dados rhs.

As duas funções especiais (cursor_after e cursor_before_or_at) também têm um efeito colateral: quando são usadas, Kusto emite o valor atual do cursor do banco de dados para o conjunto de resultados @ExtendedProperties da consulta. O nome da propriedade do cursor é Cursore seu valor é um único string.

Por exemplo:

{"Cursor" : "636040929866477946"}

Restrições

Os cursores de banco de dados só podem ser usados com tabelas para as quais o de política IngestionTime está habilitado. Cada registro nessa tabela é associado ao valor do cursor do banco de dados que estava em vigor quando o registro foi ingerido. Como tal, a função ingestion_time() pode ser usada.

O objeto cursor do banco de dados não contém nenhum valor significativo, a menos que o banco de dados tenha pelo menos uma tabela que tenha uma política IngestionTime definida. Este valor é garantido para atualizar, conforme necessário pelo histórico de ingestão, em tais tabelas e as consultas executadas, que fazem referência a tais tabelas. Poderia, ou não, ser atualizado noutros casos.

O processo de ingestão primeiro confirma os dados, para que fiquem disponíveis para consulta, e só então atribui um valor real do cursor a cada registro. Consultar dados imediatamente após a ingestão usando um cursor de banco de dados pode não incorporar os últimos registros adicionados porque o valor do cursor ainda não foi atribuído. Além disso, recuperar o valor atual do cursor do banco de dados repetidamente pode retornar o mesmo valor, mesmo que a ingestão tenha sido feita no meio, porque apenas uma confirmação do cursor pode atualizar seu valor.

Consultar uma tabela com base em cursores de banco de dados só é garantido para "funcionar" (fornecendo garantias exatamente uma vez) se os registros forem ingeridos diretamente nessa tabela. Se você usar comandos extensions, como .move extents ou .replace extents para mover dados para a tabela, ou se estiver usando tabela .rename, não é garantido consultar esta tabela usando cursores de banco de dados para evitar a falta de dados. Isso ocorre porque o tempo de ingestão dos registros é atribuído quando ingerido inicialmente e não muda durante a operação de extensões de movimento.

Quando as extensões são movidas para a tabela de destino, o valor do cursor atribuído pode já ter sido processado e a próxima consulta pelo cursor do banco de dados perderá os novos registros.

Exemplo: Processar registos exatamente uma vez

Para uma tabela Employees com esquema [Name, Salary], para processar continuamente novos registros à medida que são ingeridos na tabela, use o seguinte processo:

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