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 ...
fonte
Respostas:
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
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.
fonte
productID
seria um FK paraproduct.id
, eoptionID
é um FK paraoption.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.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.
fonte
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 .
fonte
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.
fonte