Trabalhar com o histórico da tabela
Para tabelas Apache Iceberg e Delta Lake, cada operação que modifica uma tabela cria uma nova versão da tabela. Use a história da informação para auditar operações, reverter uma tabela ou consultar uma tabela em um ponto específico no tempo usando a viagem do tempo.
Não use o histórico de tabelas como uma solução de backup de longo prazo para arquivamento de dados. Use apenas os últimos sete dias para operações de viagem do tempo, a menos que você tenha definido as configurações de retenção de dados e de log para um valor maior.
Recuperar história de uma tabela
Você pode recuperar informações, incluindo as operações, o usuário e o carimbo de data/hora de cada gravação em uma tabela, por meio da execução do comando DESCRIBE HISTORY. As operações são retornadas em ordem cronológica inversa.
Para as colunas que DESCRIBE HISTORY retorna, os valores na coluna operationParameters e as métricas por operação na coluna operationMetrics, consulte Esquema de histórico de tabela e métricas de operação.
A retenção do histórico da tabela é determinada pela configuração da tabela logRetentionDuration, que é de 30 dias por padrão.
A viagem do tempo e o histórico da tabela são controlados por diferentes limites de retenção. See viagem do 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 de sintaxe do Spark SQL, consulte DESCRIBE HISTORY.
Para detalhes de sintaxe de Scala, Java e Python, consulte a documentação da API do Delta Lake.
Catalog Explorer mostra a história da tabela visualmente na tab **History**.
Identifique o tipo de operação OPTIMIZE
A compactação automática, o liquid clustering e o Z-ordering aparecem no histórico da tabela como operações OPTIMIZE. Para determinar qual execução, inspecione a coluna operationParameters.
Para classificar cada operação OPTIMIZE no histórico de uma tabela, execute o seguinte:
SELECT
version,
timestamp,
CASE
WHEN operationParameters.clusterBy IS NOT NULL AND operationParameters.clusterBy <> '[]' THEN 'Liquid clustering'
WHEN operationParameters.zOrderBy IS NOT NULL AND operationParameters.zOrderBy <> '[]' THEN 'Z-ordering'
WHEN operationParameters.auto = 'true' THEN 'Auto compaction'
ELSE 'Manual OPTIMIZE'
END AS optimize_type,
operationParameters.auto AS is_auto_compaction,
operationParameters.clusterBy AS cluster_by,
operationParameters.zOrderBy AS z_order_by,
operationMetrics.numRemovedFiles AS files_compacted,
operationMetrics.numAddedFiles AS files_added,
operationMetrics.numRemovedBytes AS bytes_removed,
operationMetrics.numAddedBytes AS bytes_added
FROM (DESCRIBE HISTORY table_name)
WHERE operation = 'OPTIMIZE'
ORDER BY version DESC;
As seções a seguir descrevem cada valor de operationParameters em detalhes. Para definições das keys operationMetrics que a query anterior seleciona, consulte Métricas de operação.
Compactação automática
A compactação automática define o parâmetro auto como true. O Databricks aciona a compactação automática após uma gravação. Quando auto é false, um usuário ou Job agendado executou o comando OPTIMIZE.
Por exemplo, uma operação de compactação automática mostra o seguinte:
operationParameters: {
"auto": "true"
}
Para obter mais informações sobre compactação automática, consulte Compactação automática.
Liquid clustering
O liquid clustering preenche o parâmetro clusterBy com os nomes das colunas de clustering. Uma matriz clusterBy vazia ([]) indica apenas a compactação de arquivos.
Por exemplo, uma operação que agrupou dados pelas colunas date e region mostra o seguinte:
operationParameters: {
"clusterBy": "[\"date\",\"region\"]"
}
Para obter mais informações sobre liquid clustering, consulte Usar liquid clustering para tabelas.
Z-ordering
Z-ordering preenche o parâmetro zOrderBy com os nomes das colunas de Z-order. Uma matriz zOrderBy vazia ([]) indica que a operação não aplicou Z-ordering.
Por exemplo, uma operação que aplicou Z-ordering na coluna date mostra o seguinte:
operationParameters: {
"zOrderBy": "[\"date\"]"
}
Escopo da operação
O parâmetro predicate indica se a operação foi executada na tabela completa ou apenas em parte dela:
- Uma matriz
predicatevazia ([]) significa que a operação foi executada na tabela inteira. - Uma matriz
predicatepreenchida significa que um comandoOPTIMIZE table_name WHERE <partition_predicate>direcionado foi executado apenas nas partições que correspondem ao predicado.
Por exemplo, uma operação direcionada às partições que correspondem a year = 2024 mostra o seguinte:
operationParameters: {
"predicate": "[\"'year = 2024\"]"
}
viagem do tempo
A viagem do tempo é compatível com a consulta de versões anteriores da tabela com base no carimbo de data/hora ou na versão da tabela (conforme registrado no log de transações). Você pode usar a viagem do tempo para aplicações como as seguintes:
- Recriar análises, relatórios ou resultados, como a saída de um modelo do machine learning. Isso pode ser útil para depuração ou auditoria, especialmente em indústrias regulamentadas.
- Escrever consultas temporais complexas.
- Corrigir erros em seus dados.
- Fornecer isolamento de instantâneos para um conjunto de consultas para tabelas que mudam rapidamente.
No Databricks Runtime 18.0 e acima, as consultas de viagem do tempo são bloqueadas se elas solicitarem uma versão mais antiga do que a propriedade de tabela deletedFileRetentionDuration (default 7 dias). Para tabelas gerenciadas pelo Unity Catalog, isso se aplica ao Databricks Runtime 12.2 e acima.
Sintaxe da viagem do tempo
Você consulta uma tabela com viagem do tempo adicionando uma cláusula após a especificação do nome da tabela.
-
timestamp_expressionpode ser qualquer um dos seguintes:'2018-10-18T22:15:12.013Z', isto é, uma string que pode ser convertida em um carimbo de data/horacast('2018-10-18 13:36:32 CEST' as timestamp)'2018-10-18', ou seja, uma string de datacurrent_timestamp() - interval 12 hoursdate_sub(current_date(), 1)- Qualquer outra expressão que seja ou possa ser convertida em um carimbo de data/hora
-
versioné um valor longo que pode ser obtido da saída deDESCRIBE HISTORY table_spec.
Nem timestamp_expression nem version podem ser subconsultas.
Somente strings de data ou carimbo de data/hora são aceitas. Por exemplo, "2019-01-01" e "2019-01-01T00:00:00.000Z". Consulte o seguinte código para ver um exemplo de sintaxe:
- SQL
- Python
SELECT * FROM people10m TIMESTAMP AS OF '2018-10-18T22:15:12.013Z';
SELECT * FROM people10m VERSION AS OF 123;
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. É possível especificar uma versão com @v. Consulte o seguinte código para sintaxe de exemplo:
- SQL
- Python
-- Timestamp version
SELECT * FROM people10m@20190101000000000
-- Version number
SELECT * FROM people10m@v123
# Timestamp version
spark.read.table("people10m@20190101000000000")
# Version number
spark.read.table("people10m@v123")
Configurar a retenção de dados para consultas de viagem do tempo
Para consultar uma versão de tabela anterior, você deve reter *tanto* o log quanto os arquivos de dados para essa versão:
- Os arquivos de dados são excluídos quando
VACUUMé executado em uma tabela. - Os arquivos de log são removidos automaticamente após a criação de pontos de verificação das versões da tabela.
Para aumentar o limite de retenção de dados para tabelas, você deve configurar as seguintes propriedades de tabela, substituindo <format> por delta ou iceberg:
-
<format>.logRetentionDuration = "interval <interval>": controla por quanto tempo o histórico de uma tabela é mantido. O padrão éinterval 30 days.- No Databricks Runtime 18.0 e acima,
logRetentionDurationdeve ser maior ou igual adeletedFileRetentionDuration. Para tabelas gerenciadas do Unity Catalog, isso se aplica ao Databricks Runtime 12.2 e acima.
- No Databricks Runtime 18.0 e acima,
-
<format>.deletedFileRetentionDuration = "interval <interval>": determina que o limite que oVACUUMutiliza para remover arquivos de dados não é mais referenciado na versão da tabela atual. O padrão éinterval 7 days.
Por exemplo, para acessar 30 dias de data histórica, defina delta.deletedFileRetentionDuration = "interval 30 days", o que corresponde à configuração default para delta.logRetentionDuration.
Aumentar o limite de retenção de dados pode fazer com que seus custos de armazenamento subam, pois mais arquivos de dados são mantidos.
Você pode especificar as propriedades da tabela durante a criação da tabela ou defini-las com uma instrução ALTER TABLE. Consulte Referência de propriedades da tabela.
Exemplos de viagem do tempo
Para corrigir exclusões acidentais em uma tabela para o usuário 111:
INSERT INTO my_table
SELECT * FROM my_table TIMESTAMP AS OF date_sub(current_date(), 1)
WHERE userId = 111
Para corrigir atualizações incorretas acidentais em uma 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 consultar 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 de log de transações
O log de transações registra as versões da tabela como arquivos JSON dentro do diretório de log de transações junto com os dados da tabela.
Para otimizar a consulta de pontos de verificação, as versões da tabela são agregadas a arquivos de ponto de verificação Parquet, o que melhora o desempenho ao evitar a necessidade de ler todas as versões JSON da história da tabela. Os usuários não precisam interagir diretamente com os pontos de verificação.
O Databricks otimiza a frequência de pontos de verificação para o tamanho dos dados e a carga de trabalho. A frequência dos pontos de verificação está sujeita a alterações sem aviso prévio.
Restaurar uma tabela para um estado anterior
Use o comando RESTORE para restaurar uma tabela para uma versão anterior ou carimbo de data/hora, incluindo para estes cenários:
- Você pode restaurar uma tabela já restaurada.
- Você pode restaurar uma tabela clonada.
Considere os seguintes requisitos:
- Para restaurar uma tabela, você deve ter a permissão
MODIFYpara a tabela. - Depois que os arquivos de dados são excluídos, manualmente ou por
VACUUM, você não pode restaurar uma tabela para uma versão mais antiga que faça referência a esses arquivos. A restauração para essa versão ainda é possível parcialmente sespark.sql.files.ignoreMissingFilesestiver definido comotrue. - Para restaurar por carimbo de data/hora, 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 da sintaxe, consulte RESTORE.
Comportamento de transmissão
A restauração é uma operação de alteração de dados e pode resultar em dados duplicados para cargas de trabalho downstream. Entradas de log adicionadas pelo comando RESTORE contêm dataChange definido como true.
Para cargas de trabalho downstream, como um Job de transmissão estructurada que processa as atualizações em uma tabela, as entradas de log de alteração de dados adicionadas pela operação de restauração são consideradas novas atualizações de dados, e o processamento delas pode resultar em dados duplicados.
Por exemplo:
Versão da tabela | Operação | Atualizações de log | Registros em atualizações de log de alterações de dados |
|---|---|---|---|
0 |
|
| (name = Viktor, age = 29), (name = George, age = 55) |
1 |
|
| (name = George, age = 39) |
2 |
|
| Nenhum registro. A compactação |
3 |
|
| (name = Viktor, age = 29), (name = George, age = 55), (name = George, age = 39) |
No exemplo anterior, o comando RESTORE resulta em atualizações que foram vistas anteriormente ao ler a versão 0 e 1 da tabela. Se uma query de transmissão ler essa tabela novamente, esses arquivos serão considerados dados recém-adicionados e processados novamente.
Restaurar métricas
Após a conclusão, RESTORE informa as seguintes métricas como um DataFrame de linha única:
-
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 arquivos removidos (excluídos logicamente) da tabela. -
num_restored_files: número de arquivos restaurados devido à reversão. -
removed_files_size: Tamanho total em bytes dos arquivos removidos da tabela. -
restored_files_size: Tamanho total em bytes dos arquivos restaurados.
Localizar a última versão do commit
Para obter o número da versão do último commit gravado pelo SparkSession atual em todos os threads e todas as tabelas, consulte a configuração SQL spark.databricks.<format>.lastCommitVersionInSession. Substitua <format> por delta ou iceberg, dependendo do formato da sua tabela.
Por exemplo:
- SQL
- Python
- Scala
SET spark.databricks.delta.lastCommitVersionInSession
spark.conf.get("spark.databricks.delta.lastCommitVersionInSession")
spark.conf.get("spark.databricks.delta.lastCommitVersionInSession")
Se nenhum commit tiver sido feito pelo SparkSession, consultar a chave retornará um valor vazio.
Se você compartilhar o mesmo SparkSession em vários threads, é semelhante ao compartilhamento de uma variável em vários threads. Você pode encontrar condições de corrida para atualizações concorrentes no valor da configuração.