Como lidar com o design da tabela com colunas variáveis

16

Eu tenho um cenário de design de tabela e, como um tipo não DBA, gostaria de opiniões sobre qual é mais escalável.

Digamos que você seja solicitado a registrar informações sobre casas em uma área metropolitana, começando com um pequeno bairro (200 casas), mas eventualmente aumentando para 5000000+ casas.

Você precisa armazenar informações de base: ID # (um lote único # que podemos usar como índice exclusivo), Endereço, Cidade, Estado, CEP. Mesa fina e simples vai lidar com isso.

Mas a cada ano, você será solicitado a registrar informações extras sobre todas as casas - e O QUE mudará a cada ano. Por exemplo, no primeiro ano, você deve registrar o sobrenome do proprietário e a metragem quadrada. No segundo ano, você será solicitado a manter o sobrenome, mas despeje a metragem quadrada e comece a coletar os nomes dos proprietários.

Por fim - a cada ano, o número de colunas extras será alterado. Pode começar com 2 colunas extras, depois passar para 6 no próximo ano e depois voltar para 2.

Portanto, uma abordagem de tabela é tentar adicionar as informações personalizadas como colunas nas tabelas da casa, para que haja apenas uma tabela.

Mas eu tenho uma situação em que alguém colocou as tabelas para isso como:

Colunas "Tabela da casa": ID, Endereço, Cidade, Estado, CEP - com uma linha por casa

ID   Addr              City     State  Zip 
-------------------------------------------
1    10 Maple Street   Boston      MA  11203

2    144 South Street  Chelmsford  MA  11304

3    1 Main Avenue     Lowell      MA  11280

Colunas "Tabela de informações personalizadas": ID, Nome, Valor - com a tabela semelhante a:

ID   Name             Value

1    Last Name        Smith

2    Last Name        Harrison

3    Last Name        Markey

1    Square Footage   1200

2    Square Footage   1930

3    Square Footage 

Portanto, existem várias linhas para cada registro individual da casa. A cada ano, quando as informações opcionais necessárias são alteradas, essa tabela é literalmente reconstruída; portanto, no próximo ano, ela poderá se parecer com:

1    Last Name    Smith

2    Last Name    Harrison

3    Last Name    Markey

1    First Name   John

2    First Name   Harry

3    First Name   Jim

Eventualmente, você acumula 100.000 linhas de casas E, em um ano, há 10 informações extras; a segunda tabela agora é de 1.000.000 de linhas de informações, muitas das quais com informações redundantes (de descrição). Os requisitos gerais do banco de dados são que as pessoas precisarão obter as informações da linha da casa + os valores de campos personalizados associados milhares de vezes por dia.

Então, minha pergunta: seria uma prática ruim (ou horrível) substituir:

A) Coloque a tabela da casa com palpites no máximo de colunas personalizadas (talvez chamadas de "1" a "10") e insira esses valores personalizados diretamente nas linhas da casa

OU

B) Armazene as informações personalizadas na tabela da empresa, mas a cada ano, quando os requisitos forem alterados, reconstrua a tabela da empresa apenas com o número de colunas necessárias para obter informações personalizadas, com a ideia de que os requisitos podem ficar loucos e você nunca sabe quantos campos opcionais podem ser solicitados?

Obrigado, espero que isso faça sentido!

Schmitty23
fonte
Olá, como você gerencia seu problema? Estou executando o mesmo tipo de cenário e estou prestes a criar uma tabela relacional por informações extras e renderizá-la com visualizações como uma "tabela única".
25419 Benj

Respostas:

15

Você tem praticamente quatro opções:

NoSQL - definition Todo registro é armazenado como um conjunto de pares Chave / Valor. É muito flexível e rápido. Nem todos os redatores de relatórios por aí suportam esse estilo de armazenamento. Existem muitos exemplos de implementações de banco de dados do NoSQL. O que parece ser mais popular no momento, é o MongoDB.

EAV - definição Aqui é onde você vira a tabela inteira ou uma parte (em outra tabela) de lado. Essa é uma boa opção se você já possui um banco de dados relacional interno do qual não pode se afastar facilmente. O exemplo da tabela de informações personalizadas que você deu é um bom exemplo de uma tabela EAV.

Tabelas padrão com colunas XML - pense nisso como o NoSQL atende a tabelas relacionais. Os dados armazenados em uma coluna XML podem ser qualquer formato que o XML suporte, incluindo vários sub-dados correlacionados. Para as colunas que você sabe que serão colunas "regulares", elas podem ser criadas como o tipo apropriado de coluna para armazenar os dados (Sobrenome, Endereço, Cidade, Estado, etc.).

Tabelas padrão com muitas colunas extras - Você possui um banco de dados relacional, não pode usar XML ou EAV, e o NoSQL não é uma opção. Adicione muitas colunas extras de cada tipo. Eu acho que 30 ou mais varchar, 30 ou mais números inteiros, 15 ou mais números. E depois de usar uma coluna para um valor, não a reutilize . E não exclua a coluna também.

De todas essas soluções, minha opinião é que você encontrará a abordagem NoSQL ou EAV como a mais bem-sucedida, com a menor quantidade de refatoração do código e do esquema.

Você terá uma situação em que coletará dados em um ano, e não no próximo, e depois os coletará novamente posteriormente. Tentar atualizar os dados mais antigos com as informações corretas é problemático e caro. Armazenamento não é nenhum.

Adam Zuckerman
fonte
Ouvi dizer que você também pode usar tabelas dinâmicas ou algo parecido
Alexander Mills
2

Para responder sua pergunta sobre essas duas opções, nenhuma delas parece certa para mim. A) trava você e B) dá muito trabalho. O esquema atual que você descreve não é tão ruim (exceto por ter o nome das informações ("primeiro nome", "pé quadrado" etc.) como string em vez de um ID referenciado a uma tabela de pesquisa.

No entanto, isso me parece um bom candidato para um banco de dados NoSQL ( http://en.wikipedia.org/wiki/NoSQL ). Embora eu nunca tenha trabalhado com esse banco de dados, o que você descreve é ​​um cenário típico que isso resolve.

ETL
fonte
0

Se o número simultâneo de colunas personalizadas for finito e os limites forem conhecidos (por exemplo, não mais que 10-20 colunas personalizadas para String, não mais que x colunas para números inteiros etc.),
você poderia usar a tabela base com campos extras por tipo de dados e, em vez disso, de reconstruir a tabela todos os anos, crie uma exibição para esse ano, incluindo apenas as colunas personalizadas relevantes e renomeie os campos genéricos para refletir o conteúdo desse ano.

House Table:
ID, Addr, City, State, Zip, custom_string1,cs_2,cs_3,custom_integer_1,ci_2,ci_3 ...

create view house_2014 as 
select ID, Addr, City, State, Zip,
custom_string1 as last_name,cs_2 as first_name ...

O problema dessa abordagem é que você não tem histórico, mas pode fazer uma cópia facilmente todos os anos antes de alterar os requisitos da coluna.

create table house_2014_archive as select * from house_2014;
drop house_2014;
create view house_2015 as "select column list for new year";
scheelec
fonte
0

Você pode enumerar todos os cenários para os quais deseja armazenar esses dados?

se houver um número finito de combinações de colunas que possam ser aplicadas à tabela, tente modelar uma "tabela base" com colunas comuns que serão aplicadas a todos os cenários e crie mais tabelas (para implementar algum tipo de herança; isso é conhecido como subtipo / supertipo no ERD e no design do banco de dados.)

uma tabela para cada cenário, dessa forma, pelo menos, você manterá as tabelas limpas e evitará que o endereço seja armazenado na coluna "sobrenome" ...

dê uma olhada nesta pergunta de design: /programming/554522/something-like-inheritance-in-database-design

Joe
fonte