Essa é uma maneira ridícula de estruturar um esquema de banco de dados ou estou perdendo completamente alguma coisa?


61

Eu trabalhei bastante com bancos de dados relacionais e acho que entendo muito bem os conceitos básicos de bom design de esquema. Recentemente, fui encarregado de assumir um projeto em que o DB foi projetado por um consultor altamente pago. Por favor, deixe-me saber se meu intestino intacto - "WTF ??!?" - é garantido, ou esse cara é um gênio que está operando fora do meu reino?

O DB em questão é um aplicativo interno usado para inserir solicitações de funcionários. Apenas olhando uma pequena seção, você tem informações sobre os usuários e informações sobre a solicitação que está sendo feita. Eu projetaria isso assim:

Tabela do usuário:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

Tabela de solicitação

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

Simples, certo?

O consultor o projetou assim (com dados de amostra):

UsersTable

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

Departamentos

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

RequestTable

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

Todo o banco de dados é construído assim, com todos os dados encapsulados em sua própria tabela, com IDs numéricos vinculando tudo. Aparentemente, o consultor havia lido sobre OLAP e queria a "velocidade das pesquisas de números inteiros"

Ele também possui um grande número de procedimentos armazenados para fazer referência cruzada a todas essas tabelas.

Esse design é válido para um banco de dados SQL de pequeno a médio porte?

Obrigado por comentários / respostas ...


12
Oh garoto, se isso faz você dizer WTF, provavelmente você não viu tabelas com mais de 200 colunas e procedimentos armazenados com mais de 1000 linhas.
Job

42
+1 por não excluir depois de se sentir envergonhado. Obrigado por deixar isso para que outros possam aprender.
Wayne Koorts

2
@ Job - na verdade, eu não tenho - eu não sou um DBA por comércio (bastante óbvio agora! Lol), então meu limite WTF SQL é bastante baixo. Embora eu não tenha entendido completamente o objetivo do projeto do consultor, fiz com que eu tivesse minhas próprias habilidades. Já teve um dia em que você se sente burro ?
Jim

9
@ Jim: Parabéns, você transformou um dia idiota em um dia iluminado .
Wayne Koorts

3
Amaldiçoe aqueles consultores altamente pagos!
Davidsleeps

Respostas:


73

Faz todo o sentido para mim. É apenas muito normalizado, o que confere muita flexibilidade que você não teria de outra maneira. Dados não normalizados são uma dor no traseiro.


sua resposta faz todo sentido, e examinar minha pergunta e o esquema talvez seja apenas o grande número de tabelas que ele está usando que me confundiu. Simplifiquei bastante o exemplo da minha pergunta, mas vejo como o conceito é sólido - ele está apenas dividindo as coisas muito mais do que eu faria. Suspiro, acho que é bom eu não ser um DBA! :)
Jim

Aprenda a projetar pela regra dos dez minutos: "O que é verdade agora provavelmente não será em dez minutos". Certifique-se de que seus projetos possam lidar com mudanças.
Blrfl

11
Na verdade, esse esquema tem a vantagem de que, quando um funcionário é inserido, seu departamento precisa existir.
Simon Richter

@ SimonRichter: Não é verdade. O Funcionário pode ser criado sem nenhum departamento existente e também o contrário.
Daniel Dinnyes

@SimonRichter O benefício desse projeto é, primeiramente, que o Departamento seja uma entidade separada e, segundo, que exista um relacionamento muitos-para-muitos entre o Departamento e o Funcionário, em oposição ao exemplo dos OPs, onde havia "muitos- to-one-ish "(não era possível dizer muitos-para-um, pois nenhuma entidade separada do Departamento que estava referenciando era chamada de relacionamento).
Daniel Dinnyes

48

Eu não acho que um WTF seja garantido ou que o cara esteja desenvolvendo algum tipo de design genial - é uma normalização de banco de dados bastante padrão.

O motivo da tabela de departamentos é que, se você não colocar os departamentos em uma tabela separada, precisará lidar com os usuários nos departamentos "Vendas", "Vendas", "Vendedores", "Velas" e "Venda", a menos que você faça algo para evitá-lo. E ter uma mesa extra é (parte de) a melhor maneira que sei fazer isso.

Se deve haver uma tabela UserDepartment é uma decisão mais difícil, o que obviamente significa que nenhuma das decisões é exagerada. Por um lado, é uma dor quando todo o design e a lógica de sua mesa assumiram um departamento por usuário e isso muda, por outro lado, fazer uma junção extra sem motivo por anos e anos é uma possibilidade real e também uma dor.

Pessoalmente, eu concordo com você que a tabela UserDepartment provavelmente é um exagero. Mesmo se incluído, as chances são de que, com o tempo, as pessoas escrevam consultas que pressupõem que haja apenas um usuário por departamento, para que você acabe com o pior dos dois mundos - uma junção extra sem motivo antes de precisar da tabela, e código não funciona de qualquer maneira, uma vez que mais de um departamento por usuário é permitido.

EDIT - Um fator importante para saber se o relacionamento entre muitos e muitos deve ser suportado é se as regras de negócios são claras. Se você não tem idéia de como um usuário em vários departamentos funcionaria, não faz muito sentido adicionar a tabela, pois seu código não pode lidar corretamente com os casos em que um usuário está em vários departamentos.

Imagine que você permitiu muitos departamentos por usuário, apenas por precaução. Você implementou uma regra de negócios para atribuir comissões, com base no departamento. Em seguida, vários departamentos foram permitidos. Felizmente, você também teve a previsão de escrever seu código de comissão de uma maneira que levasse isso em consideração. Infelizmente, você adicionou as comissões de cada departamento para usuários de ambos. A gerência queria que você baseasse na função de pessoas para cada venda. Então, quanto de bom era ter a mesa com antecedência? E as outras tabelas que você tinha "apenas por precaução" que nunca são necessárias?

EDIÇÃO MAIS TARDE - Outro motivo pelo qual o consultor pode querer adicionar todas essas tabelas intermediárias é abordado nesta pergunta de acompanhamento , cujas respostas dão algumas razões pelas quais a refatoração de um banco de dados é geralmente mais difícil do que o código de refatoração, o que tenderia a empurrá-lo para a abordagem "coloque todas as tabelas que você possa precisar".


Eu acho que você colocou em palavras qual era minha WTF - o cara está usando TONELADAS dessas tabelas intemídia, e isso me pareceu tão estúpido. Agora que o dividi em um exemplo muito menor para essa pergunta, me sinto um pouco estúpido por postar, pois não parece tão ruim.
Jim

5
Como você pode ver em muitos comentários, há um ceticismo saudável sobre os comentários "haverá apenas um X por Y". O consultor está se escondendo das reclamações de "como é que só pode haver um X por Y". Alguns dos quais provavelmente aparecerão. Mas ele não será responsável por manter o código que possui muitas associações (não muito ruins, mas mais difíceis) e que deve estar correto contra as regras de negócios que ainda não existem (ruins) - imagine a pergunta "por que os usuários obtêm ALL as permissões de cada departamento, eles devem obter o MAIS BAIXO de cada permissão "ou algo parecido.
Psr

@ psr Acho que há um erro de digitação: "consultas que pressupõem que existe apenas um usuário por departamento" devem "consultas que supõem que um usuário esteja em apenas um departamento"?
BiAiB 30/09

@BiAiB - você está correto, é isso que eu quis dizer.
Psr

14

Se o requisito é ter vários departamentos por usuário, esse design faz sentido. A única reclamação sobre isso é UserDepartmentTableter uma chave substituta UserDepartmentIDque não é necessária (basta criar a chave primária composta UserIde DepartmentId).

Se um usuário pertencer apenas a um único departamento, seu design fará sentido (embora uma tabela de pesquisa de departamento ainda seja uma coisa boa).


18
... Até mais de um departamento ser possível por usuário.
Blrfl

11
Exatamente, @Blrfl. O que nunca vai acontecer hoje é o CEO de amanhã que está tendo um aneurisma porque não faz isso.
Adam Crossland

2
Parte da decisão sobre o que é digno desse tipo de tratamento é entender o domínio do problema. Em algumas aplicações, pode ser importante saber que o funcionário nº 3804 é conhecido pela empresa como Ann Smith e Ann Jones (após o casamento), o que tornaria a normalização do nome da mesa dos funcionários uma coisa sã a ser feita. No caso de Jim, pode valer a pena expandir a tabela de interruptores para manter um histórico, para que, se Ann passar de RH para TI, o fato de uma solicitação antiga vinculada a ela possa refletir que realmente era uma solicitação de RH e não de TI.
Blrfl

8
YAGNI - os bancos de dados podem ser refatorados.
JeffO 29/09

2
@Oded, Alguns mapeadores ORM como o Entity Framework não funcionam bem com tabelas que possuem uma chave primária composta.
maple_shaft

5

Alguns requisitos não estão claros na sua pergunta. A resposta correta depende do que seu cliente deseja - se eu fosse você, perguntaria ao cliente sobre isso:

0-Qual é a diferença entre um usuário e um funcionário?

1-Supondo que um funcionário = usuário, e se um funcionário mudar de departamento?

2-Um grupo de funcionários pode fazer 1 solicitação?

3-Um funcionário poderia pertencer a mais de um departamento? E o CEO

4-Existe um subconjunto de funcionários com permissão para fazer solicitações?

5-O que acontece com a solicitação quando um registro de funcionário é excluído (se houver)?

6-Você pode excluir uma solicitação? O que acontece quando a solicitação é excluída (certifique-se de não excluir o registro do funcionário pelo RI)

7-O funcionário pode fazer o "mesmo" pedido mais de uma vez (definir o "mesmo")

8-Como lidar com solicitações de funcionários quando elas saem da empresa (cancelar suas solicitações ou excluir as solicitações?)

Pode haver mais perguntas, mas o que quero dizer é que a solução depende dos requisitos exatos e do escopo do projeto. Uma vez determinado, o esquema pode ser derivado diretamente. Por conseguinte, ambas as soluções apresentadas podem estar corretas.


Com +1, essas são ótimas perguntas que precisam ser esclarecidas antes de projetar esse tipo de esquema. Eu gosto do seu fluxo de lógica.

@ Surfer513: Agradeço o seu bom comentário.
NoChance

1

Eu gostaria de acrescentar algumas notas do formulário falando explicitamente sobre algumas das vantagens potenciais de usar uma tabela de junção da maneira que seu consultor altamente pago fez.

  • Indexado corretamente (por exemplo, se UserDepartmentTable indexa as duas chaves estrangeiras), há apenas uma pequena perda de desempenho de uma tabela de junção como esta devido ao fato de as chaves estrangeiras não serem exclusivas. Se é garantido que as chaves estrangeiras são únicas, de acordo com a pequena teoria do banco de dados que conheço, olhar para cima UserDepartmentTable.Departmentnão é "mais difícil" do que procurar qualquer outra coluna na Usertabela.
  • A tabela de junção oferece mais flexibilidade para configurar outras informações sobre a associação entre o usuário e o departamento (por exemplo, registros de data e hora na criação).
  • A tabela de junção permite que você "versão" da associação com bastante facilidade (por exemplo, quando um usuário altera os departamentos, aciona algum sinalizador booleano do índice, como UserDepartmentTable.Activefalso e cria uma nova associação que está ativa). Também é possível ter versões de associação de departamentos com o modelo de duas tabelas (apenas Usuário e Departamento), mas é mais difícil e requer a adição de pelo menos mais uma coluna ou acrobacias no banco de dados para evitar a duplicação de chaves primárias.
  • Permite atribuir associações um-para-muitos ou muitos-para-um ou muitos-para-muitos com bastante facilidade.

Dito isto, há várias razões para NÃO fazer o que seu consultor altamente pago fez.

  • Todos os benefícios acima são antecipatórios de possíveis necessidades futuras, complicando demais as coisas para os dias atuais. Não é compatível com YAGNI. Mais tarde, é uma dificuldade trivial escrever uma migração que passe do seu modelo de duas tabelas para um modelo de tabela de junção. Você pode fazer isso quando surgir a necessidade comercial. Fazer isso antes disso pode ser confuso.
  • Confunde outros desenvolvedores. Embora, sim, eu diria que a expectativa de um desenvolvedor web de sua estatura (onde você está revendo as decisões dos consultores) seria entender e reconhecer uma tabela de junção, ainda é mais complicado do que o necessário, e considerando a falta de necessidade comercial, causa confusão.

boa análise - no entanto, eu não diria que tenho estatura como desenvolvedor no meu trabalho diário, exceto que sou o único aqui que sabe alguma coisa sobre db / c # / vb / etc ... então acho que faço parte time dev por padrão. Este é um relativamente pequeno projeto, assim que a consultores pura número de mesas e junções me deixou dizer "wtf" (mas graças a você bem popular agora estou dizendo "OIC ...")
Jim

Um tópico antigo, mas ainda relevante ... a refatoração pode ser muito difícil, imagine que você precise de vários departamentos no futuro em vez de um, mas tenha apenas um ID de departamento em Usuários como FK. Você provavelmente terminará com referências duplicadas (Users.DeptID e UsersDepartmentsTable) ou lixo completo, como listas separadas por vírgula em Users.DeptID ou XML. A solução correta não pode ser facilmente adicionada, como sugerido por YAGNI ou KISS, mas seria obstruída.
Erik Hart

0

Sem a estrutura completa das informações necessárias, não posso dizer que seja terrível ou não. Mas pelo menos a peça mostrada não é do tipo "WTF". Parece que é a terceira forma normal de estrutura de dados (bem, teoricamente também temos a quarta e a quinta)

Algumas conversas podem ter lugar para UserDepartmentTable entre duas escolas de chaves "naturais" e "artificiais" na peça mostrada. Nada mais, como posso ver

A normalização é uma regra do bom desenvolvedor / desenvolvedor de banco de dados por várias razões, * de * normalizações são usadas algumas vezes no meio dos desenvolvimentos para ganhar velocidade principalmente

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.