Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Para as tabelas Apache Iceberg e Delta Lake, cada operação que modifica uma tabela cria uma nova versão da tabela. Use informação histórica para auditar operações, reverter uma tabela ou consultar uma tabela num ponto específico no tempo usando viagens no tempo.
Note
O Databricks não recomenda usar o histórico de tabelas como solução de backup a longo prazo para arquivamento de dados. Use apenas os últimos 7 dias para operações de viagem no tempo, a menos que tenha definido tanto as configurações de dados como de retenção de registos para um valor maior.
Recuperar histórico da tabela
Execute o DESCRIBE HISTORY comando para recuperar informações incluindo as operações, o utilizador e o carimbo temporal de cada gravação numa tabela. As operações são retornadas em ordem cronológica inversa.
A retenção do histórico da tabela é determinada pela configuração da tabela logRetentionDuration, que é de 30 dias por padrão.
Note
A viagem no tempo e o histórico das tabelas são controlados por diferentes limites de retenção. Ver Viagem no tempo.
DESCRIBE HISTORY table_name -- get the full history of the table
DESCRIBE HISTORY table_name LIMIT 1 -- get the last operation only
Para obter detalhes da sintaxe do Spark SQL, consulte DESCRIBE HISTORY.
Para detalhes da sintaxe em Scala, Java e Python, consulte a documentação da API Delta Lake.
O Explorador de Catálogos mostra visualmente o histórico da tabela no separador Histórico .
Esquema do histórico
A saída da operação history tem as seguintes colunas.
| Coluna | Tipo | Description |
|---|---|---|
| versão | long |
A versão da tabela gerada pela operação. |
| carimbo de data/hora | timestamp |
Quando esta versão foi cometida. |
| userId | string |
O ID do utilizador que executou a operação. |
| userName | string |
O nome do utilizador que executou a operação. |
| operação | string |
O nome da operação. |
| parâmetros de operação | map |
Os parâmetros da operação (por exemplo, predicados.) |
| tarefa | struct |
Os detalhes da tarefa do Lakeflow que executou a operação. É preenchido apenas para commits efetuados por uma tarefa do Lakeflow. Caso contrário, null. |
| bloco de notas | struct |
Os detalhes do caderno Databricks a partir do qual a operação foi executada. É preenchido apenas para commits efetuados a partir de um notebook do Databricks. Caso contrário, null. |
| clusterId | string |
O ID do cluster onde a operação decorria. |
| lerVersão | long |
A versão da tabela que foi lida para realizar a operação de escrita. |
| isolationLevel | string |
O nível de isolamento utilizado nesta operação. |
| isBlindAppend | boolean |
Se esta operação anexou dados. |
| operationMetrics | map |
As métricas da operação (por exemplo, número de linhas e ficheiros modificados.) |
| userMetadata | string |
Os metadados de commit definidos pelo utilizador, caso tenham sido especificados. |
+-------+-------------------+------+--------+---------+--------------------+----+--------+---------+-----------+-----------------+-------------+--------------------+
|version| timestamp|userId|userName|operation| operationParameters| job|notebook|clusterId|readVersion| isolationLevel|isBlindAppend| operationMetrics|
+-------+-------------------+------+--------+---------+--------------------+----+--------+---------+-----------+-----------------+-------------+--------------------+
| 5|2019-07-29 14:07:47| ###| ###| DELETE|[predicate -> ["(...|null| ###| ###| 4|WriteSerializable| false|[numTotalRows -> ...|
| 4|2019-07-29 14:07:41| ###| ###| UPDATE|[predicate -> (id...|null| ###| ###| 3|WriteSerializable| false|[numTotalRows -> ...|
| 3|2019-07-29 14:07:29| ###| ###| DELETE|[predicate -> ["(...|null| ###| ###| 2|WriteSerializable| false|[numTotalRows -> ...|
| 2|2019-07-29 14:06:56| ###| ###| UPDATE|[predicate -> (id...|null| ###| ###| 1|WriteSerializable| false|[numTotalRows -> ...|
| 1|2019-07-29 14:04:31| ###| ###| DELETE|[predicate -> ["(...|null| ###| ###| 0|WriteSerializable| false|[numTotalRows -> ...|
| 0|2019-07-29 14:01:40| ###| ###| WRITE|[mode -> ErrorIfE...|null| ###| ###| null|WriteSerializable| true|[numFiles -> 2, n...|
+-------+-------------------+------+--------+---------+--------------------+----+--------+---------+-----------+-----------------+-------------+--------------------+
Note
- Se escrever numa tabela usando os seguintes métodos, algumas colunas não estão disponíveis:
- As colunas adicionadas no futuro serão sempre adicionadas após a última coluna.
Compreensão partitionBy dos parâmetros de operação
O partitionBy campo no histórico da tabela só tem significado para operações CREATE e OVERWRITE que definem ou alteram o esquema de partição de uma tabela.
Para operações de acréscimo a tabelas existentes (APPEND, INSERT, UPDATE, DELETE, MERGE), este campo pode mostrar uma matriz [] vazia ou colunas de partição, dependendo do método de gravação usado (.save() vs .saveAsTable()).
Esta inconsistência é um comportamento esperado e não afeta a forma como os dados são escritos nas partições. Não deves usá-lo para validar operações de anexação.
Example
Considere uma tabela particionada pela date coluna. Quando crias a tabela, partitionBy é preenchido:
df.write.format("delta") \
.partitionBy("date") \
.saveAsTable("sales_data")
A operação CREATE no histórico mostra:
operationParameters: {
"mode": "ErrorIfExists",
"partitionBy": "[\"date\"]"
}
Quando adiciona dados a esta tabela, partitionBy mostra um array vazio:
new_df.write.format("delta") \
.mode("append") \
.saveAsTable("sales_data")
A operação APPEND mostra:
operationParameters: {
"mode": "Append",
"partitionBy": "[]"
}
O valor vazio partitionBy é esperado. Os dados ainda são gravados nas partições corretas com base no esquema de partição existente da tabela. Tenha em atenção que .save() para um caminho pode mostrar colunas de partição neste campo, mas esta diferença é um detalhe de implementação e não afeta o comportamento de escrita.
Métricas de operação
A operação history retorna uma coleção de métricas de operações no mapa de colunas operationMetrics.
As tabelas a seguir listam as definições de chave do mapa por operação.
WRITE, CREATE TABLE AS SELECT, REPLACE TABLE AS SELECT, COPY INTO
As seguintes métricas estão disponíveis para estas operações:
| Nome da métrica | Description |
|---|---|
numFiles |
O número de ficheiros escritos. |
numOutputBytes |
O tamanho em bytes do conteúdo escrito. |
numOutputRows |
O número de linhas escritas. |
STREAMING UPDATE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numAddedFiles |
O número de ficheiros adicionados. |
numRemovedFiles |
O número de ficheiros removidos. |
numOutputRows |
O número de linhas escritas. |
numOutputBytes |
O tamanho da operação de escrita, em bytes. |
DELETE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numAddedFiles |
O número de ficheiros adicionados. Não fornecido quando as partições da tabela são excluídas. |
numRemovedFiles |
O número de ficheiros removidos. |
numDeletedRows |
O número de linhas removidas. Não fornecido quando as partições da tabela são excluídas. |
numCopiedRows |
O número de linhas copiadas no processo de eliminação de ficheiros. |
executionTimeMs |
O tempo necessário para executar toda a operação. |
scanTimeMs |
O tempo necessário para analisar os ficheiros à procura de correspondências. |
rewriteTimeMs |
O tempo necessário para reescrever os ficheiros correspondentes. |
TRUNCATE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numRemovedFiles |
O número de ficheiros removidos. |
executionTimeMs |
O tempo necessário para executar toda a operação. |
MERGE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numSourceRows |
O número de linhas no DataFrame de origem. |
numTargetRowsInserted |
O número de linhas inseridas na tabela alvo. |
numTargetRowsUpdated |
O número de linhas atualizadas na tabela alvo. |
numTargetRowsDeleted |
O número de linhas eliminadas na tabela alvo. |
numTargetRowsCopied |
O número de linhas alvo copiadas. |
numOutputRows |
O número total de linhas escritas. |
numTargetFilesAdded |
O número de ficheiros adicionados ao sumidouro (alvo). |
numTargetFilesRemoved |
O número de ficheiros removidos do lavatório (alvo). |
executionTimeMs |
O tempo necessário para executar toda a operação. |
scanTimeMs |
O tempo necessário para analisar os ficheiros à procura de correspondências. |
rewriteTimeMs |
O tempo necessário para reescrever os ficheiros correspondentes. |
UPDATE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numAddedFiles |
O número de ficheiros adicionados. |
numRemovedFiles |
O número de ficheiros removidos. |
numUpdatedRows |
O número de linhas atualizadas. |
numCopiedRows |
O número de linhas foi simplesmente copiado durante o processo de atualização dos ficheiros. |
executionTimeMs |
O tempo necessário para executar toda a operação. |
scanTimeMs |
O tempo necessário para analisar os ficheiros à procura de correspondências. |
rewriteTimeMs |
O tempo necessário para reescrever os ficheiros correspondentes. |
FSCK
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numRemovedFiles |
O número de ficheiros removidos. |
CONVERT
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numConvertedFiles |
O número de ficheiros Parquet que foram convertidos. |
OPTIMIZE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numAddedFiles |
O número de ficheiros adicionados. |
numRemovedFiles |
O número de ficheiros otimizados. |
numAddedBytes |
O número de bytes adicionados após a tabela foi otimizado. |
numRemovedBytes |
O número de bytes removidos. |
minFileSize |
O tamanho do ficheiro mais pequeno após a tabela foi otimizado. |
p25FileSize |
O tamanho do ficheiro no 25.º percentil depois de a tabela ter sido otimizada. |
p50FileSize |
O tamanho mediano do ficheiro após a tabela foi otimizado. |
p75FileSize |
O tamanho do ficheiro do percentil 75 depois de a tabela ter sido otimizada. |
maxFileSize |
O tamanho do maior ficheiro após a tabela foi otimizado. |
CLONE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
sourceTableSize |
O tamanho em bytes da tabela de origem na versão que foi clonada. |
sourceNumOfFiles |
O número de ficheiros na tabela de origem na versão que foi clonada. |
numRemovedFiles |
O número de ficheiros removidos da tabela de destino se uma tabela anterior fosse substituída. |
removedFilesSize |
O tamanho total em bytes dos ficheiros removidos da tabela de destino se uma tabela anterior foi substituída. |
numCopiedFiles |
O número de ficheiros que foram copiados para a nova localização. 0 para clones superficiais. |
copiedFilesSize |
O tamanho total em bytes dos ficheiros que foram copiados para a nova localização. 0 para clones superficiais. |
RESTORE
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
tableSizeAfterRestore |
O tamanho da tabela em bytes após a restauração. |
numOfFilesAfterRestore |
O número de ficheiros na tabela após a restauração. |
numRemovedFiles |
O número de ficheiros removidos pela operação de restauro. |
numRestoredFiles |
O número de ficheiros adicionados como resultado da restauração. |
removedFilesSize |
O tamanho em bytes dos ficheiros removidos pela restauração. |
restoredFilesSize |
O tamanho em bytes dos ficheiros adicionados pela restauração. |
VACUUM
As seguintes métricas estão disponíveis para esta operação:
| Nome da métrica | Description |
|---|---|
numDeletedFiles |
O número de ficheiros apagados. |
numVacuumedDirectories |
O número de diretórios limpos com o aspirador. |
numFilesToDelete |
O número de ficheiros a apagar. |
Viagem no tempo
A viagem no tempo suporta consultar versões anteriores das tabelas, registadas no registo de transações, com base no timestamp ou na versão da tabela. Você pode usar a viagem no tempo para aplicativos como os seguintes:
- Recriar análises, relatórios ou resultados, como o resultado de um modelo de aprendizagem automática. Isto pode ser útil para depuração ou auditoria, especialmente em indústrias reguladas.
- Escrever consultas temporais complexas.
- Corrigir erros nos seus dados.
- Proporcionar isolamento ao nível de instantâneo para um conjunto de consultas em tabelas de rápida mutação.
Note
No Databricks Runtime 18.0 e superiores, as consultas de versão temporal são bloqueadas se solicitarem uma versão anterior à propriedade da tabela deletedFileRetentionDuration (padrão 7 dias). Para tabelas geridas pelo Unity Catalog, isto aplica-se ao Databricks Runtime 12.2 e superiores.
Sintaxe da viagem no tempo
Consulta uma tabela com viagem no tempo adicionando uma cláusula após a especificação do nome da tabela.
-
timestamp_expressionpode ser qualquer um:-
'2018-10-18T22:15:12.013Z', ou seja, uma cadeia de caracteres que pode ser convertida num timestamp cast('2018-10-18 13:36:32 CEST' as timestamp)-
'2018-10-18', ou seja, uma cadeia de caracteres de data current_timestamp() - interval 12 hoursdate_sub(current_date(), 1)- Qualquer outra expressão que seja ou possa ser convertida num marca temporal
-
-
versioné um valor longo que pode ser obtido a partir da saída deDESCRIBE HISTORY table_spec.
Nem timestamp_expression nem version podem ser subconsultas.
Somente cadeias de caracteres de data ou carimbo de data e hora são aceitas. Por exemplo, "2019-01-01" e "2019-01-01T00:00:00.000Z". Consulte o seguinte código para exemplo de sintaxe:
SQL
SELECT * FROM people10m TIMESTAMP AS OF '2018-10-18T22:15:12.013Z';
SELECT * FROM people10m VERSION AS OF 123;
Python
df1 = spark.read.option("timestampAsOf", "2019-01-01").table("people10m")
df2 = spark.read.option("versionAsOf", 123).table("people10m")
Você também pode usar a sintaxe @ para especificar o carimbo de data/hora ou a versão como parte do nome da tabela. O carimbo de data/hora deve estar no formato yyyyMMddHHmmssSSS. Pode especificar uma versão com @v. Consulte o seguinte código para exemplo de sintaxe:
SQL
-- Timestamp version
SELECT * FROM people10m@20190101000000000
-- Version number
SELECT * FROM people10m@v123
Python
# Timestamp version
spark.read.table("people10m@20190101000000000")
# Version number
spark.read.table("people10m@v123")
Configurar a retenção de dados para consultas de viagem no tempo
Para consultar uma versão anterior da tabela, deve manter tanto o registo como os ficheiros de dados dessa versão:
- Os arquivos de dados são eliminados quando
VACUUMé executado numa tabela. - Os ficheiros de registo são removidos automaticamente após a criação de pontos de verificação das versões da tabela.
Para aumentar o limiar de retenção de dados para tabelas, deve configurar as seguintes propriedades da tabela, substituindo <format> por delta ou iceberg:
-
<format>.logRetentionDuration = "interval <interval>": controla por quanto tempo o histórico de uma tabela é mantido. A predefinição éinterval 30 days.- Em Databricks Runtime 18.0 e superiores,
logRetentionDurationdeve ser maior ou igual adeletedFileRetentionDuration. Para tabelas geridas pelo Unity Catalog, isto aplica-se ao Databricks Runtime 12.2 e superiores.
- Em Databricks Runtime 18.0 e superiores,
-
<format>.deletedFileRetentionDuration = "interval <interval>": determina o limiteVACUUMusa para remover arquivos de dados que não são mais referenciados na versão atual da tabela. A predefinição éinterval 7 days.
Por exemplo, para aceder a 30 dias de dados históricos, defina delta.deletedFileRetentionDuration = "interval 30 days", que corresponde à definição padrão para delta.logRetentionDuration.
Important
Aumentar o limite de retenção de dados pode fazer com que os custos de armazenamento aumentem, à medida que mais arquivos de dados são mantidos.
Pode especificar propriedades de tabela durante a criação da tabela ou defini-las com uma ALTER TABLE instrução. Consulte Referência de Propriedades da Tabela.
Exemplos de viagens no tempo
Para corrigir eliminações acidentais numa tabela para o utilizador 111:
INSERT INTO my_table
SELECT * FROM my_table TIMESTAMP AS OF date_sub(current_date(), 1)
WHERE userId = 111
Para corrigir atualizações acidentais e incorretas numa tabela:
MERGE INTO my_table target
USING my_table TIMESTAMP AS OF date_sub(current_date(), 1) source
ON source.userId = target.userId
WHEN MATCHED THEN UPDATE SET *
Para questionar o número de novos clientes adicionados na última semana:
SELECT
(
SELECT count(distinct userId)
FROM my_table
)
-
(
SELECT count(distinct userId)
FROM my_table TIMESTAMP AS OF date_sub(current_date(), 7)
) AS new_customers
Pontos de verificação do registo de transações
O registo de transações regista as versões das tabelas como ficheiros JSON dentro do diretório do registo de transações, juntamente com os dados das tabelas.
Para otimizar a consulta de checkpoints, as versões das tabelas são agregadas em ficheiros de checkpoint Parquet, o que melhora o desempenho ao evitar a necessidade de ler todas as versões JSON do histórico das tabelas. Os utilizadores não precisam de interagir diretamente com os pontos de controlo.
O Azure Databricks otimiza a frequência de pontos de verificação para o tamanho dos dados e a carga de trabalho. A frequência do ponto de verificação está sujeita a alterações sem aviso prévio.
Restaurar uma tabela a um estado anterior
Use o RESTORE comando para restaurar uma tabela a uma versão ou carimbo temporal anterior, incluindo nestes cenários:
Considere os seguintes requisitos:
- Para restaurar uma tabela, tem de ter a permissão
MODIFYpara a tabela. - Depois de os ficheiros de dados serem eliminados, manualmente ou por
VACUUM, não podes restaurar uma tabela para uma versão antiga que faça referência a esses ficheiros. A restauração parcial para esta versão ainda é possível sespark.sql.files.ignoreMissingFilesestiver definida comotrue. - Para restaurar por carimbo temporal, use os formatos
yyyy-MM-dd HH:mm:ssouyyyy-MM-dd.
RESTORE TABLE target_table TO VERSION AS OF <version>;
RESTORE TABLE target_table TO TIMESTAMP AS OF <timestamp>;
Para obter detalhes de sintaxe, consulte RESTORE.
Comportamento de streaming
A restauração é uma operação que altera dados e pode resultar em dados duplicados para cargas de trabalho posteriores. As entradas de registo adicionadas pelo RESTORE comando contêm dataChange definido como true.
Para cargas de trabalho a jusante, como um trabalho de streaming estruturado que processa as atualizações de uma tabela, as entradas do registo de alterações de dados adicionadas pela operação de restauro são consideradas novas atualizações de dados, e o seu processamento pode resultar em dados duplicados.
Por exemplo:
| Versão da tabela | Operation | Atualizações dos registos | Registos nas atualizações do registo de alterações de dados |
|---|---|---|---|
| 0 | INSERT |
AddFile(/path/to/file-1, dataChange = true) |
(nome = Viktor, idade = 29), (nome = George, idade = 55) |
| 1 | INSERT |
AddFile(/path/to/file-2, dataChange = true) |
(nome = George, idade = 39) |
| 2 | OPTIMIZE |
AddFile(/path/to/file-3, dataChange = false), RemoveFile(/path/to/file-1), RemoveFile(/path/to/file-2) |
Nenhum registo.
OPTIMIZE a compactação não altera os dados na tabela. |
| 3 | RESTORE(version=1) |
RemoveFile(/path/to/file-3), AddFile(/path/to/file-1, dataChange = true), AddFile(/path/to/file-2, dataChange = true) |
(nome = Viktor, idade = 29), (nome = George, idade = 55), (nome = George, idade = 39) |
No exemplo anterior, o RESTORE comando resulta em atualizações que já tinham sido vistas ao ler as versões 0 e 1 da tabela. Se uma consulta de streaming ler esta tabela novamente, então estes ficheiros são considerados dados recém-adicionados e são processados novamente.
Restaurar métricas
Após concluir, RESTORE reporta as seguintes métricas como uma única linha de DataFrame:
table_size_after_restore: O tamanho da tabela após a restauração.num_of_files_after_restore: O número de arquivos na tabela após a restauração.num_removed_files: Número de ficheiros removidos (logicamente eliminados) da tabela.num_restored_files: Número de arquivos restaurados devido à reversão.removed_files_size: Tamanho total, em bytes, dos ficheiros que são removidos da tabela.restored_files_size: Tamanho total em bytes dos arquivos que são restaurados.
Encontre a última versão de commit
Para obter o número da versão do último commit feito pelo atual SparkSession em todos os threads e em todas as tabelas, execute uma consulta na configuração SQL spark.databricks.<format>.lastCommitVersionInSession. Substitua <format> por delta ou iceberg, consoante o formato da sua tabela.
Por exemplo:
SQL
SET spark.databricks.delta.lastCommitVersionInSession
Python
spark.conf.get("spark.databricks.delta.lastCommitVersionInSession")
Scala
spark.conf.get("spark.databricks.delta.lastCommitVersionInSession")
Se nenhuma confirmação tiver sido feita pelo SparkSession, consultar a chave retornará um valor vazio.
Note
Se partilhar o mesmo SparkSession entre vários threads, é semelhante a partilhar uma variável entre vários threads. Podes encontrar condições de corrida para atualizações simultâneas do valor de configuração.