Cria ou não tabelas separadas para diferentes tipos de produtos?

25

Estou no processo de projetar um banco de dados e estou tendo dúvidas sobre minhas decisões iniciais de design ...

Os tipos de produtos são os seguintes ... Modelos, peças, kits de peças de reposição e opções.

Opção A (primeiro design): planejei ter tabelas separadas para os tipos de produtos acima. Eu diria que cerca de 75% dos campos seriam os mesmos em cada tabela.

Criei cada tipo de produto como tabelas separadas por causa das associações que preciso criar entre elas. Por exemplo, um modelo pode ter muitas opções e uma opção pode ter muitos modelos. Uma opção também pode ter muitas partes e uma parte pode ter muitas opções ... e assim por diante ...

Opção B: Em vez de ter tabelas separadas, eu poderia criar uma tabela chamada Produto que engloba modelo, peça, kits de peças de reposição e opções. Eu poderia ter um campo chamado type para diferenciar entre modelo, opções, etc. Suponho que um lado negativo é que vários campos nunca seriam usados ​​(deixados nulos) para determinados tipos de produtos. Acho que é aqui que "as melhores práticas" não entram em jogo.

A opção B reduziria bastante a complexidade do design do banco de dados. Também não precisaria me preocupar em fazer referência a várias tabelas ao extrair dados para consultas ...

pagamento
fonte
2
Nesse ponto, sugiro que você crie planilhas que imitem o layout da sua tabela e as preencham com dados. Isso irá expor quaisquer pontos fracos que possam existir.
Michael Riley - AKA Gunny
Como você apontará chaves estrangeiras para produtos diferentes se eles estiverem em tabelas diferentes? Leia sobre a herança da tabela, por favor.
Neil McGuigan

Respostas:

8

Se essa fosse minha decisão de design, provavelmente eu usaria mais uma 'Opção C' (opção modificada a).

Primeiro, por que não a 'Opção B':

Por um lado, gosto da clareza de que cada produto possui sua própria tabela. Se for uma tabela grande com um campo para determinar o tipo, a relação não é tão clara.

Por outro lado, a estratégia de indexação sempre exigiria a listagem desse campo de tipo. Como são apenas quatro tipos, a cardinalidade do índice é extremamente baixa ( SELECT * FROM product_table WHERE type='X'basicamente faz uma verificação completa da tabela)

Opção C

  • Crie uma tabela pai que contém apenas as colunas que todos os tipos compartilham
  • Crie cada tipo de produto como sua própria tabela com suas colunas individuais, com um extra: Um link para a tabela pai
  • Crie cada tabela de 'links': Opção_do_Produto, Opção_do_Modelo, etc. com links para as respectivas chaves.
  • Para aqueles com links recíprocos (MODEL_OPTION, OPTION_MODEL), vá em frente e crie essas tabelas também. Isso adicionará clareza nas suas junções para quem estiver olhando.

A desvantagem é a complexidade de evitar órfãos quando as coisas são atualizadas / excluídas e, inicialmente, projetar as consultas que usam essas tabelas.

Derek Downey
fonte
5
Existem apenas quatro tipos agora, mas e se mais forem adicionados mais tarde? Tenho certeza de que a tabela principal de produtos da Amazon era originalmente chamada de "Livros", mas você acha que eles têm uma tabela separada para cada tipo de produto agora? Eu não acho que cada tipo deve ter sua própria tabela, mas você pode usar um modelo EAV para propriedades adicionais que cada tipo possa ter em comum.
Aaron Bertrand
11
@Aaron Fair comenta sobre o futuro aumento de tipos de produtos. Se esse cenário pudesse expandir-se para mais de 10 tipos de produtos, eu reconsideraria. Mas sinto que tabelas específicas de produtos são uma escolha justa de design para uma pequena quantidade de tipos de produtos.
Derek Downey
11
Opção C: é necessário ter uma tabela de links? Eu imaginaria que a PK Product_Option corresponderia à PK da tabela Product e isso criaria a associação para vincular as duas tabelas.
payling
Usando Product_option como exemplo, o esquema seria (em minha mente): id, productID, optionID. productIDseria um FK para product.id, e optionIDé um FK para option.id. Isso é o que eu quis dizer com tabela de links. E sim, é necessário neste design permitir que um único produto vincule a várias opções.
Derek Downey
Ok, eu entendo. Eu interpretei errado o que você digitou .. Opa.
payling
7

Eu sugiro que você comece com o modelo relacional "correto", sua opção A. Se o uso típico desse modelo leva você à desnormalização em algumas áreas, não tenha medo de fazê-lo.

Eu estava discutindo com um colega na semana passada como os designs de esquemas são frequentemente considerados algo que é imutável e que nunca pode mudar. Estranho, considerando o quão prática é a refatoração em todas as outras camadas de um aplicativo, que a refatoração de um esquema de banco de dados ainda é vista como impraticável.

Se a interface com o banco de dados for bem projetada, nada impedirá a adaptação do esquema à medida que você aprender mais sobre os padrões de uso do sistema.

Mark Storey-Smith
fonte
2

Isso soa muito semelhante à herança de listas de materiais / múltiplas cardinalidades que Paul Neilsen descreve no capítulo 17 da Bíblia do SQL Server 2008 .

O capítulo inteiro é uma leitura muito boa e a seção específica que trata do problema de muitos para muitos pode ser encontrada nas páginas 416-419.

Esta é a melhor discussão que eu já vi sobre o tipo de design de dados de peças explodidas .

Michael Riley - também conhecido por Gunny
fonte
Essa solução é semelhante à opção B (se eu entendi direito, o que não tenho certeza). Eu teria uma tabela mestre (Produtos) e uma tabela "link" (também conhecida como tabela adjacente / BillsofMaterials) para criar as associações entre modelos, opções, kits etc. Isso está correto?
payling
Acho que o problema está nublado por causa das opções. Vamos tirar opções da discussão por um tempo. As peças são a menor unidade. Um grupo de peças compõe um modelo. Um grupo de peças de reposição na forma de um kit compõe um subconjunto do modelo. Por enquanto, tudo bem. Agora, as peças têm opções, vamos assumir, por uma questão de simplicidade, que abrange duas categorias de cores (preto, vermelho, cromo) e material (metal, madeira, plástico). Você também mencionou que os modelos têm opções. As opções do modelo são separadas das opções da peça ou os modelos parecem ter apenas opções porque as peças diferenciam os modelos?
Michael Riley - também conhecido como Gunny
As peças não têm "opções" no meu design. Eu defino opção como algo que se aplica a um modelo que fornece funcionalidade estendida. Uma opção é composta de peças. Um modelo pode ter muitas opções diferentes. Uma opção também pode ser usada em muitos modelos diferentes.
payling
Não foi assim que você formulou sua pergunta. Citação: "Por exemplo, um modelo pode ter muitas opções e uma opção pode ter muitos modelos. Uma opção também pode ter muitas partes e uma parte pode ter muitas opções ... e assim por diante ..." Neste ponto, sugiro que você crie planilhas que imitem o layout da sua tabela e as preencham com dados. Isso irá expor quaisquer pontos fracos que possam existir.
Michael Riley - AKA Gunny
0

Se você conseguir criar imagens de um cenário provável em que haveria consultas frequentes entre os quatro tipos de produtos (e isso me parece provável), sua opção B é a melhor.

Em vez de deixar muitos campos anuláveis ​​não utilizados na tabela Produto, por que não adicionar uma tabela ModelProduct, uma tabela PartProduct, uma tabela ReplacementPartKitProduct e ter apenas os campos que são distintos para esses tipos nessas tabelas? Use a mesma chave primária nessas tabelas que sua tabela de produtos. Associe-se à tabela Product e ModelProduct quando desejar trabalhar com modelos. Precisa determinar se o registro do produto que você possui é uma peça? Basta fazer uma junção esquerda de Product para PartProduct e, se o PartProduct. [PrimaryKey] não for nulo, você terá uma Part. Se for nulo, não é uma parte. Como alternativa, você pode adicionar um campo ProductType à tabela Product.

Alan McBee
fonte
Os campos nulos seriam mínimos, porque aproximadamente 75% dos campos seriam usados ​​em todas as tabelas. Acho que estou mais preocupado com as relações entre os tipos de produtos. Vou ter três tabelas de links apontando para a mesma tabela. Model_has_Option duas chaves primárias, ambos os IDs de produtos da tabela de produtos, se eu usasse apenas uma tabela para representar os tipos de produtos. Estou mais preocupado se é a coisa certa a fazer ou não.
payling 27/07
Embora existam muitos fatores que afetam a decisão "correta", há dois fatores amplos a serem considerados. 1: requisitos gerais de desempenho; 2: adaptabilidade / complexidade / manutenção. Um desses dois provavelmente é um pouco mais importante que o outro. Se você precisar de velocidade, desnormalize aderindo à Opção A. Você terá duplicação; isso é esperado. Se você precisar mexer no esquema regularmente e a velocidade não for O fator mais importante, a Opção B. Você acertará em tudo ao conhecer suas prioridades, não em aderir às "melhores práticas de outra pessoa".
27711 Alan McBee