22 pontos por GN⁺ 2025-04-25 | 3 comentários | Compartilhar no WhatsApp
  • No PostgreSQL, mesmo ao dar DROP em uma coluna, os dados não são realmente apagados — eles apenas ficam "ocultos" nos metadados
  • Como a coluna continua existindo internamente mesmo após o DROP COLUMN, é possível atingir o limite de 1600 colunas
  • Para remover os dados por completo, é necessário usar VACUUM FULL ou reescrita manual da tabela
  • Isso é um design voltado para otimização de desempenho, mas exige atenção do ponto de vista de conformidade, como no GDPR
  • Entender "o que realmente acontece" ajuda em resolução de problemas, otimização de desempenho e gerenciamento de dados

Como o DROP COLUMN realmente funciona no PostgreSQL

O problema: e se você adicionar/remover colunas repetidamente?

  • Com um código como o abaixo, uma coluna é adicionada e removida 2000 vezes:
    ALTER TABLE t ADD COLUMN c1 int;  
    ALTER TABLE t DROP COLUMN c1;  
    ...  
    
  • No fim, embora só restem 2 colunas na tabela, o PostgreSQL ainda gera um erro de limite de 1600 colunas
  • O motivo? As colunas removidas ainda continuam existindo internamente

O que acontece dentro do PostgreSQL?

Remover uma coluna não é uma "remoção de verdade"

  • O PostgreSQL armazena dados em páginas de 8 KB
  • Remover fisicamente uma coluna exigiria reescrever a tabela inteira, o que seria ineficiente
  • Em vez disso, a coluna é marcada como 'dropped' nos metadados e ignorada

Dá para verificar isso na tabela de sistema pg_attribute

SELECT attnum, attname, attisdropped FROM pg_attribute WHERE attrelid = 'test2'::regclass AND attnum > 0;  
  • Exemplo de saída:
    attnum | attname                  | attisdropped  
    --------+--------------------------+--------------  
          1 | a                        | f  
          2 | ........pg.dropped.2.... | t  
          3 | c                        | f  
    
  • Colunas com attisdropped = t são ignoradas nas queries, mas continuam lá internamente

Verificando no arquivo de dados (com pg_filedump)

  • Ao analisar o arquivo de dados do PostgreSQL, é possível confirmar que os valores da coluna removida ainda permanecem lá
  • Nos dados antigos (Item 1), existem valores para 3 colunas
  • Nos dados inseridos após a remoção (Item 3), esse valor de coluna não existe mais e passa a ser tratado como NULL

Como remover de fato uma coluna apagada

1. VACUUM FULL

  • Reescreve a tabela inteira e remove também os dados da coluna apagada
  • Desvantagem: a própria coluna ainda continua existindo em pg_attribute, no estado 'dropped'

2. Reescrita manual da tabela

  • Crie uma nova tabela e copie apenas as colunas necessárias com SELECT
    CREATE TABLE new_table AS SELECT a, c FROM old_table;  
    
  • Restrições, índices, triggers etc. precisam ser recriados manualmente
  • Também é possível usar pg_dump: fazer backup → editar o arquivo de dump → restaurar

DROP COLUMN e o problema do "direito ao esquecimento" no GDPR

  • Algumas pessoas levantam a preocupação: "se a coluna não é realmente apagada, isso não viola o GDPR?"
  • Mas a remoção de dados pessoais normalmente é feita no nível de linha (row)
    DELETE FROM users WHERE id = <user_id>; -- ou remover também das tabelas relacionadas  
    
  • O DROP COLUMN não tem relação direta com o GDPR; o essencial é modelar e apagar corretamente os dados pessoais

Pontos de atenção

  • Como o PostgreSQL usa MVCC, mesmo após apagar uma linha, os dados continuam existindo até que o VACUUM seja concluído
  • No nível do sistema operacional, também pode haver apenas um "marcador de exclusão" em vez de remoção física imediata
  • Do ponto de vista jurídico, o importante costuma ser um "esforço razoável de exclusão"; apagar completamente o disco físico geralmente não é exigido

Conclusão: DROP COLUMN é mais "ocultar" do que "apagar"

  • É uma escolha de design focada em desempenho, mas o acúmulo de colunas pode bater no limite de 1600
  • Quando necessário, use VACUUM FULL ou reescrita da tabela para limpar os dados
  • Entender o funcionamento interno do PostgreSQL é muito útil para arquitetura de sistemas e conformidade

Referências

3 comentários

 
ohyecloudy 2025-04-30

A perspectiva de que uma escolha de implementação para otimização de desempenho também pode ser pensada em relação ao direito ao esquecimento da GDPR é bem perspicaz. No fim, a conclusão é que o essencial é modelar e excluir corretamente os dados pessoais, então não há relação direta. Bem elegante.

 
click 2025-04-25

Embora o postgresql esteja bem popular ultimamente, eu prefiro implementações de MVCC em que as áreas de redo/undo existem separadamente.
Como dá para sacrificar um pouco a operação em tempo real nas áreas de redo/undo, também existe espaço para otimizar custos usando armazenamento de categoria mais baixa.
Também não gosto do fato de que, em algum momento, é preciso bloquear o banco de dados inteiro e executar um VACUUM FULL.

 
salsa 2025-04-26

Isso significa que, em algum momento, é realmente necessário fazer VACUUM FULL? Pelo que vi na maioria dos documentos, quase sempre recomendam não fazer isso.

Uma das referências que vi:
https://www.depesz.com/2023/02/06/when-to-use-vacuum-full/