Projetar e implementar um esquema de particionamento de dados

Concluído(a)

O particionamento de dados afeta diretamente a eficiência da execução das consultas e a quantidade de recursos de computação que você consome. Ao particionar uma tabela, você divide dados em segmentos discretos com base em valores de coluna, permitindo que o mecanismo de consulta leia apenas partes relevantes do seu conjunto de dados. Essa abordagem, chamada de poda de partição, pode reduzir drasticamente as verificações de dados quando os filtros se alinham com os limites de partição.

Considere uma empresa de varejo processando milhões de transações diárias de vendas. Analistas frequentemente consultam dados por intervalos de datas para gerar relatórios semanais, comparar tendências mês a mês e analisar padrões sazonais. Sem particionamento, cada consulta examina todo o histórico de transações. Com o particionamento adequado por data, as consultas de uma semana específica tocam apenas uma fração dos arquivos armazenados.

Determinar quando o particionamento se aplica

O Databricks recomenda que você não particione tabelas contendo menos de 1 TB de dados. Para tabelas menores, a sobrecarga do gerenciamento de metadados de partição e o potencial para criar muitos arquivos pequenos superam os benefícios de desempenho da consulta. Em versões recentes do Databricks Runtime, as tabelas Delta não particionadas beneficiam-se automaticamente do clustering de tempo de ingestão, que fornece vantagens de consulta semelhantes sem configuração explícita.

Quando suas tabelas excedem 1 TB, o particionamento se torna uma técnica de otimização valiosa. Nessa escala, os benefícios de ler apenas segmentos de dados relevantes compensam significativamente os custos do gerenciamento de partição. O particionamento também permite o processamento paralelo, pois o Spark pode distribuir diferentes partições entre nós de cluster para execução simultânea.

Importante

Cada partição deve conter pelo menos 1 GB de dados. Essa diretriz ajuda você a evitar o particionamento excessivo, o que cria arquivos pequenos excessivos e degrada o desempenho da consulta.

Diagrama que ajuda a determinar quando o particionamento se aplica.

Para tabelas muito grandes no intervalo de centenas de terabytes, o particionamento oferece benefícios ainda maiores. Nessa escala, a poda de partição reduz drasticamente a quantidade de dados que o mecanismo de consulta precisa processar, melhorando tanto o desempenho quanto a eficiência de custo.

Escolher chaves de partição efetivas

A seleção de chave de partição exige que você entenda suas características de dados e padrões de consulta. Chaves de partição eficazes compartilham características comuns que maximizam os benefícios de desempenho, evitando armadilhas comuns.

Colunas de baixa cardinalidade funcionam melhor

Escolha colunas com um número limitado de valores distintos. Colunas de data, regiões geográficas, categorias de produto e campos de status fazem chaves de partição excelentes porque criam um número gerenciável de partições. Uma coluna com milhares ou milhões de valores exclusivos, como ID do cliente ou ID de transação, leva a particionamento excessivo e baixo desempenho.

Por exemplo, particionar uma tabela de vendas por sale_date no nível diário pode criar 365 partições por ano. Se cada dia contiver volume de dados suficiente, essa granularidade funcionará bem. No entanto, o particionamento no sale_timestamp segundo nível criaria milhões de partições, cada uma contendo dados mínimos.

Alinhar com padrões de consulta

Sua chave de partição deve corresponder às colunas que os usuários filtram com mais frequência. Se os analistas consultarem consistentemente os dados de vendas por intervalos de datas, o particionamento por data permitirá uma poda eficiente. Se as consultas filtrarem principalmente por região, considere a região como sua chave de partição.

Quando existirem vários padrões de filtro, priorize as consultas mais comuns ou críticas ao desempenho. Você pode definir um esquema de particionamento por tabela, portanto, escolha colunas que beneficiem a maior parte da carga de trabalho. Para padrões de consulta significativamente diferentes, considere a criação de exibições materializadas com otimização separada ou tabelas de resumo para casos de uso específicos.

Considere o crescimento de dados ao longo do tempo

Selecione um esquema de partição que é dimensionado adequadamente à medida que seus dados crescem. O particionamento por ano funciona bem inicialmente, mas pode criar partições muito grandes ao longo do tempo. Por outro lado, o particionamento por hora pode funcionar para dados de alto volume, mas cria muitas partições pequenas para volumes moderados.

Avalie a taxa de crescimento de dados esperada ao escolher a granularidade da partição. Um equilíbrio entre o tamanho da partição e o número de partições ajuda a manter o desempenho de consulta consistente à medida que o conjunto de dados se expande.

Considere também a distribuição de dados entre partições. Tamanhos de partição severamente irregulares podem criar gargalos de processamento, pois os nós que lidam com partições maiores levam mais tempo para serem concluídos, enquanto outros permanecem ociosos.

Implementar partições no Azure Databricks

Você define partições ao criar uma tabela usando a PARTITIONED BY cláusula no SQL ou o partitionBy método no PySpark. Depois de estabelecer partições, o Azure Databricks roteia automaticamente os dados de entrada para os diretórios de partição apropriados com base nos valores de coluna.

Criar uma tabela particionada com SQL

O exemplo a seguir cria uma tabela de transações de vendas particionada pela data da transação:

CREATE TABLE sales.transactions (
    transaction_id STRING,
    customer_id STRING,
    product_id STRING,
    quantity INT,
    unit_price DECIMAL(10,2),
    total_amount DECIMAL(12,2),
    transaction_date DATE
)
PARTITIONED BY (transaction_date);

Quando você consulta essa tabela com um filtro de data, o mecanismo de consulta lê apenas as partições que correspondem aos critérios de filtro:

SELECT product_id, SUM(total_amount) AS revenue
FROM sales.transactions
WHERE transaction_date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY product_id;

Criar uma tabela particionada com o PySpark

Ao usar o PySpark, especifique o particionamento durante a operação de gravação:

df.write.format("delta") \
    .partitionBy("transaction_date") \
    .saveAsTable("sales.transactions")

Para gravações subsequentes, mantenha a consistência incluindo a mesma especificação de partição:

new_transactions_df.write.format("delta") \
    .mode("append") \
    .partitionBy("transaction_date") \
    .saveAsTable("sales.transactions")

Usar colunas geradas para flexibilidade de partição

As colunas geradas fornecem uma maneira de derivar valores de partição de colunas existentes sem armazenar dados redundantes. Essa abordagem é útil quando os dados de origem contêm carimbos de data/hora, mas você deseja particionar por data:

CREATE TABLE sales.transactions (
    transaction_id STRING,
    customer_id STRING,
    product_id STRING,
    quantity INT,
    unit_price DECIMAL(10,2),
    total_amount DECIMAL(12,2),
    transaction_timestamp TIMESTAMP,
    transaction_date DATE GENERATED ALWAYS AS (CAST(transaction_timestamp AS DATE))
)
PARTITIONED BY (transaction_date);

Dica

Com essa configuração, o Delta Lake gera automaticamente filtros de partição ao realizar consultas utilizando a coluna de timestamp base. Uma consulta filtrada em transaction_timestamp beneficia da poda de partição sem a necessidade de filtros de data explícitos.

Evitar erros comuns de particionamento

Entender o que evitar é tão importante quanto saber o que fazer. Vários erros comuns podem prejudicar significativamente o desempenho e complicar o gerenciamento de dados.

Diagrama explicando erros comuns de particionamento.

O particionamento excessivo cria pequenos problemas de arquivo

A criação de muitas partições, cada uma contendo dados insuficientes, leva a pequenos problemas de arquivo. Quando as partições contêm arquivos menores que o tamanho do arquivo de destino, o desempenho da consulta sofre com operações excessivas de metadados e redução da eficiência de leitura. Almeje partições com pelo menos 1 GB de dados.

Os sinais de particionamento excessivo incluem desempenho de consulta lento, apesar da poda de partição, um grande número de arquivos pequenos em diretórios de partição e tempos longos de otimização de tabela. Se você observar esses sintomas, considere escolher uma granularidade de partição mais grossa.

Falha no particionamento em colunas de alta cardinalidade

Colunas com muitos valores exclusivos criam chaves de partição ruins. Particionamento por ID do cliente, ID de transação ou outras colunas de alta cardinalidade cria milhões de partições que degradam em vez de melhorar o desempenho. Reserve otimização de coluna de alta cardinalidade para outras técnicas projetadas para essa finalidade.

Alterar partições requer a reescrita de dados

As colunas de partição fazem parte da estrutura da tabela. Alterar sua estratégia de particionamento requer reescrever a tabela inteira para um novo local com limites de partição diferentes. Essa operação consome recursos de computação significativos e tempo para tabelas grandes.

Planeje sua estratégia de particionamento cuidadosamente antes de carregar dados em escala. Considere os padrões de consulta futuros e o crescimento de dados para evitar uma reestruturação dispendiosa posteriormente.

Decisões de particionamento de documentos

Registre suas opções de chave de partição e o raciocínio por trás delas. Esta documentação ajuda os membros da equipe a entender as oportunidades de otimização de consulta e impede alterações acidentais que possam afetar o desempenho. Inclua informações sobre tamanhos de partição esperados, padrões de consulta que se beneficiam do esquema e quaisquer restrições que influenciaram suas decisões.

Considere o agrupamento de dados líquido como uma alternativa

Quando você enfrenta problemas de particionamento, especialmente lidando com colunas de alta cardinalidade como carimbos de data/hora, ou quando os padrões de consulta são incertos, o clustering líquido fornece uma alternativa moderna. Ao contrário do particionamento tradicional, o clustering líquido oferece:

  • Flexibilidade para ajustar estratégias de otimização sem reescrever dados
  • Manutenção automática à medida que as tabelas crescem
  • Sobrecarga de gerenciamento de partição reduzida

O clustering líquido é a abordagem recomendada para novas tabelas em que as restrições de particionamento limitariam o desempenho ou gerariam uma sobrecarga de manutenção excessiva. Ele é particularmente eficaz para tabelas que excedem 1 TB e exigem filtragem em colunas que criariam muitas partições usando abordagens tradicionais.

Observação

O liquid clustering não é compatível com tabelas particionadas. Escolha uma abordagem com base em seus requisitos ao criar novas tabelas.

Para obter detalhes de implementação, sintaxe e estratégias de otimização, consulte o Design e implemente uma unidade de estratégia de clustering posteriormente neste módulo.