Prática recomendada para armazenar metadados de registro

10

Qual é a melhor prática para armazenar metadados de registros individuais em um banco de dados?

Preciso armazenar metadados comuns, como hora da criação e hora da última atualização, para muitas tabelas no meu banco de dados. Encontrei algumas soluções diferentes:

  1. Armazene os metadados diretamente nas tabelas.

    Prós:

    • Os metadados estão diretamente vinculados aos registros
    • Nenhuma associação é necessária para recuperar os metadados

    Contras:

    • Muitas colunas duplicadas são necessárias (a menos que a herança seja usada)
    • Meta dados e dados comerciais não são separados
  2. Crie uma tabela de metadados geral e use teclas estrangeiras programáveis ​​para vincular dados às tabelas e registros corretos.

    Prós:

    • Sem duplicação de colunas
    • Os metadados são separados dos dados corporativos

    Contras:

    • Não há links diretos entre metadados e dados (não é possível usar FKs)
    • As junções requerem uma condição adicional
  3. Crie tabelas de metadados individuais para cada tabela que requer metadados.

    Prós:

    • Os metadados estão diretamente vinculados aos registros
    • Os metadados são separados dos dados corporativos

    Contras:

    • São necessárias muitas mesas extras
    • Muitas colunas duplicadas são necessárias (a menos que a herança seja usada)

Existem mais opções, prós ou contras do que as mencionadas aqui? E qual é a melhor prática para armazenar esses metadados?

Tiddo
fonte
De que tipo de metadados estamos falando? Talvez usar uma coluna hstoreou JSONpossa resolver seu problema?
a_horse_with_no_name 12/06
@a_horse_with_no_name - No momento, eu só preciso da hora da criação, hora da atualização e fonte de criação. Os campos são fixos, portanto, não preciso de valores-chave como armazenamento. Só estou preocupado com onde devo armazenar os dados.
Tiddo
11
Então não vejo nenhum motivo para não adicionar essas três colunas à tabela base.
a_horse_with_no_name 12/06

Respostas:

7

As colunas das quais você está falando ocupam 20 bytes (se alinhadas sem preenchimento):

hora de criação, hora da atualização e fonte de criação

registro de data e hora .. 8 bytes
registro de data e hora .. 8 bytes
inteiro .. 4 bytes

O cabeçalho da tupla e o ponteiro do item para uma linha separada em uma tabela separada ocupariam apenas 23 + 1 + 4 = 28 bytes mais os 20 bytes de dados reais, mais 4 bytes de preenchimento no final. Cria 52 bytes por linha . Leia mais aqui:

Em relação ao armazenamento, você não tem nada a ganhar. Em relação ao desempenho, você quase não perde nada com apenas 16 a 24 bytes a mais por linha.

As colunas também pertencem diretamente à linha, portanto, faz sentido mantê-las juntas. Eu tenho o hábito de adicionar exatamente essas colunas (além de fonte separada para a última atualização) a todas as tabelas relevantes.

Também é mais fácil escrever um TRIGGER ON INSERT OR UPDATEpara mantê-los atualizados.

Longa história: um voto forte para sua opção 1 .

Onde eu iria para a opção 3 :
se os metadados são atualizados com frequência, enquanto a linha principal não está. Em seguida, pode pagar para manter uma tabela 1: 1 separada para tornar as ATUALIZAÇÕES mais baratas e reduzir o inchaço na tabela principal - ou até mesmo optar pela opção 2.

Onde eu iria para a opção 2 :
se o conjunto de colunas de metadados for altamente repetitivo. Você pode ter uma coluna FK para o conjunto de metadados nas tabelas principais. Não economiza muito para três pequenas colunas, como no seu exemplo.

Erwin Brandstetter
fonte
Que tal resolver isso com a herança da tabela, existem desvantagens notáveis ​​em comparação ao uso de colunas de metadados diretamente na tabela? No entanto, se eu entendi corretamente, a herança da tabela do postgres não é compatível com o padrão SQL, não é?
devrys
11
@evevrys: A herança tem algumas limitações no Postgres Mais importante: não vejo como a herança poderia resolver salvando algumas colunas adicionais por linha. seria uma opção se você tiver algumas linhas com e outras linhas sem metadados. Mas eu não usaria isso para isso.
Erwin Brandstetter