Introdução
O Delta Lake é uma camada de armazenamento para tabelas ACID acima da camada de armazenamento de objetos ou Data Lake. Esta camada adiciona um universo de novas funcionalidades para manipulação, gestão e otimização do Data Lake.
Neste artigo você vai entender melhor como o Delta Lake, de forma automática, otimiza suas tabelas bem como podemos de forma explícita melhorar a performance de nossas consultas utilizando os comandos OPTIMIZE e Z-ORDER.
Layout Otimizado dos Dados
A camada Delta aplica uma série de otimizações em suas tabelas, de forma a garantir:
- Maior confiabilidade nos conjunto de dados por impor a aplicação de um schema
- Log transacional: Onde podemos acompanhar e auditar diferentes versões da nossa tabela.
- Transacionalidade: As transações são realizadas de forma ACID, o que possibilita o suporte a transações como UPSERT, DELETE e MERGE.
- Performance: Através de otimizações de compactação e data skipping.
Sabemos que tabelas Delta são armazenadas utilizando objetos do Apache Parquet, um formato de arquivo orientado a colunas e com integrações aprimoradas para motores como o Apache Spark e outras ferramentas no ambiente de big data.
Por padrão, um arquivo Parquet armazena em seu rodapé algumas estatísticas sobre cada coluna, como valores mínimos e máximos. Estas estatísticas permitem que os sistemas de processamento evitem ler seções desnecessárias do arquivo, tornando o processo de leitura muito mais rápido e eficiente. Este processo é conhecido como “Data Skipping” ou salto de dados.
O Data Skipping é uma técnica usada para pular blocos de dados irrelevantes para uma consulta específica, trata-se de uma técnica muito eficiente para melhor o desempenho de consultas em grandes conjuntos de dados.
O Data Skipping no Delta Lake é semelhante ao data skipping em arquivos Parquet, mas é ainda mais eficiente porque aproveita ao máximo o conhecimento sobre a estrutura de dados e o esquema da tabela. Ele também usa índices estatísticos avançados que são armazenados como metadados em um arquivo Delta Lake, para identificar quais seções de dados precisam ser lidas para responder a uma consulta.
Estes índices estatísticos são coletados automaticamente quando você escreve dados em uma tabela Delta. No Databricks você não precisa configurar esta opção, esta feature é ativada por padrão, entretanto a sua efetividade depende do layout dos seus dados.
Por padrão, no Databricks, o Delta Lake coleta estatísticas sobre as 32 primeiras colunas definidas no schema de sua tabela. Você até pode alterar a configuração padrão para considerar um número maior de colunas mas esteja ciente que quanto mais colunas maior o custo computacional.
Indices otimizados para o Z-Ordering
Para uma melhor performance em suas consultas você pode, de forma explícita, utilizar o comando Z-Order para indicar adicionalmente quais são os campos/colunas chave dentro de sua tabela para a realização de um data skipping.
Se você possui em seu conjunto de dados uma coluna que é utilizada com grande frequência como filtro em suas consultas, então poderá considerá-la como índice para o Z-Order.
Por exemplo: Você talvez possua na sua base de dados de vendas um campo relativo à “data da venda”, e na grande maioria de suas consultas costuma-se utilizar este campo como filtro.
Um campo é forte candidato para o Z-Order quando:
- É um campo chave utilizando com frequência
- Quando o campo possui alta cardinalidade, ou seja, uma série de diferentes classes. O campo gênero (Masculino ou Feminino) é um exemplo de campo a não ser utilizado pois possui baixa cardinalidade já que só assume poucos valores.
- Se sua tabela for particionada, o campo não pode ser o mesmo que o utilizado para particionamento.
Considere utilizar um número pequeno de colunas para o Z-Order, quanto mais colunas maior será o tempo de processamento para execução do comando.
Dependendo do seu caso pode não ser necessário particionar sua tabela, talvez somente o Z-Order já lhe traga a performance esperada. Para saber mais sobre particionamento de tabelas preparamos um outro artigo aqui no nosso blog.
O comando Z-Order
O comando ZORDER é utilizado em conjunto com o comando OPTIMIZE. O comando OPTIMIZE veio para aprimorar a tratativa de um dos problemas principais no armazenamento de dados em arquivos distribuídos, o problema dos “Small Files”.
Em outro artigo aqui no nosso blog falamos mais sobre Small Files e como a camada Delta Lake otimiza e resolve este problema.
Resumidamente, o comando OPTIMIZE procura por “pequenos pedaços” do seu conjunto de dados tentando agrupá-los em um arquivos maiores, diminuindo então a quantidade de arquivos necessários para manter seus dados.
A sintaxe para execução do Z-order então fica :
%sql
OPTIMIZE vendas
ZORDER BY(produto_categoria);
-- Se você deseja otimizar somente uma parte do conjunto, utilize o WHERE
OPTIMIZE vendas WHERE data_venda >= "2023-01-01" AND produto_categorias = "Eletrodomesticos"
ZORDER BY(produto_categoria);
%python
from delta.tables import DeltaTable
deltaTable = DeltaTable.forPath(spark, pathToTable) # pathToTable = caminho/location da tabela
vendas = deltaTable
vendas.optimize().executeZOrderBy(produto_categoria)
# Se você deseja otimizar somente uma parte do conjunto, utilize o WHERE
vendas.optimize() \
.where("data_venda >= '2023-01-01' AND produto_categorias = 'Eletrodomesticos'") \
.executeZOrderBy(produto_categorias)
Conclusão
Apesar de aplicar automaticamente uma série de otimizações na forma como os dados são armazenados e gerenciados a camada Delta Lake ainda nos permite adicionar uma série de parametrizações, específicas para o nosso problema de forma a obter a melhor performance possível.
referências: Databricks: Delta Lake Data Skipping