Um guia modesto para esquemas de banco de dados


Geometria das flores por Mookiezoolook

Para aplicativos que serão escalados de acordo com o tráfego e a complexidade, é extremamente importante projetar inicialmente um esquema de banco de dados competente. Se você fizer uma má escolha, terá que se esforçar muito para que esse modelo ruim não se espalhe para serviços e controladores de back-end e, finalmente, para o front-end.

Mas como avaliar qual circuito é melhor? E o que significa "melhor" quando falamos sobre arquitetura de banco de dados? A equipe do Mail.ru Cloud Solutions convida você a seguir as recomendações de Mike Alcha , consultor de desenvolvimento de software. Parece-nos que ele resumiu sucintamente alguns princípios da arquitetura competente.


Diretor: " Acho que devemos construir um banco de dados SQL " .

Desenvolvedor (ele entende o que está falando ou apenas viu algum tipo de anúncio em uma revista de negócios?): "De que cor você deseja o banco de dados? "

Diretor: Talvez o lilás tenha mais memória .

Algumas dicas básicas


Portanto, é importante lutar por duas coisas principais :

  1. Ao dividir informações em tabelas, todas as informações são armazenadas.
  2. A redundância de armazenamento é mínima.

Quanto ao segundo ponto: queremos reduzir a redundância apenas por causa de um problema com o tamanho do armazenamento? Não, fazemos isso principalmente porque a presença de dados redundantes gera problemas de inconsistência se você não atualizar todos os campos que representam as mesmas informações durante a atualização.

Aqui estão algumas diretrizes para se aproximar de boa arquitetura :

  1. Use pelo menos a terceira forma normal (na qual cada atributo que não seja a chave "deve fornecer informações sobre a chave, a chave completa e nada além da chave", de acordo com o texto de Bill Kent).
  2. Crie a última linha de defesa na forma de restrições.
  3. Nunca armazene endereços inteiros em um campo.
  4. Nunca armazene o nome e o sobrenome em um campo.
  5. Defina convenções para nomes de tabelas e campos e atenha-se a elas.


- Em que você está trabalhando?

" Otimizando esta consulta SQL." Ele fica mais lento e os usuários começam a reclamar.

- E linguagem obscena nos comentários é necessária para otimização?

- Se você visse o código original , não perguntaria.

Vamos considerar essas recomendações em mais detalhes.

1. Use pelo menos uma terceira forma normal


A arquitetura do banco de dados pode ser dividida nas seguintes categorias:

  • A primeira forma normal.
  • A segunda forma normal.
  • Terceira forma normal.
  • A forma normal de Boyce-Codd.

Essas categorias representam uma classificação por qualidade. Analisaremos brevemente todas as categorias e veremos por que é necessário pelo menos um terceiro formulário normal.

Primeira forma normal


Para a primeira forma normal, cada valor de cada coluna de cada tabela no banco de dados deve ser atômico. O que significa atômico? Em resumo, o valor atômico é uma "coisa única".

Por exemplo, temos uma tabela como esta:
primeiro nomeúltimo nomeeraáreas
JhonCorça27{"Design do site", "Pesquisa de clientes"}
MariaJane33{"Planejamento estratégico a longo prazo", "Recrutamento"}
TomSmith35{"Marketing"}

Aqui, a coluna áreas contém valores que não são atômicos. Por exemplo, em uma linha de John Doe, o campo armazena duas entidades: design do site e pesquisa do cliente.

Portanto, esta tabela não está na primeira forma normal.

Para trazê-lo para este formulário, apenas um valor deve ser armazenado em cada campo .

Segunda forma normal


Na segunda forma normal, nenhuma coluna que não faça parte da chave primária (ou que possa atuar como parte de outra chave primária) não pode ser derivada da parte menor da chave primária .

O que isso significa?

Suponha que você tenha uma arquitetura básica (enfatizei os campos correspondentes à chave primária nesta tabela):
ID do Empregadoproject_idHorasnome do empregadoNome do Projeto
1 11 110John"Design do site"
21 1vinteMaria"Design do site"

Neste projeto, o nome do funcionário pode ser inferido diretamente de employeee_id, porque a idéia é que o nome do funcionário seja determinado exclusivamente pelo seu identificador.

Da mesma forma, o nome do projeto é identificado exclusivamente pelo identificador project_id.

Portanto, temos duas colunas que podem ser deduzidas da parte da chave primária.

Cada um desses exemplos seria suficiente para eliminar essa tabela da segunda forma normal.

Outra conclusão é que, se a tabela estava na primeira forma normal e todas as chaves primárias são colunas únicas, a tabela já está na segunda forma normal.

Terceira forma normal


Para que a tabela corresponda à terceira forma normal, ela deve estar na segunda forma normal, embora não deva haver atributos (colunas) nela, exceto a principal, que depende temporariamente da chave primária.

O que isso significa?

Digamos que você tenha a seguinte arquitetura (que está longe do ideal):
nome do empregadoID do Empregadoeradepartment_numberNome do departamento
John1 127123"Marketing"
Maria233456"Operacional"
Tom335123"Marketing"

Nesta tabela, o número do departamento pode ser inferido a partir de employee_id e o nome do departamento pode ser inferido a partir do número do departamento. Portanto, department_name depende transitivamente de employee_id!

Se houver uma dependência transitiva: employee_id → department_number → department_name, essa tabela não está na terceira forma normal.

Que problemas surgem por causa disso ?

Se o nome do departamento puder ser derivado de seu número, o armazenamento desse campo para cada funcionário introduzirá redundância excessiva.

Imagine que o departamento de marketing mude seu nome para "Marketing e vendas". Para manter a consistência, você precisará atualizar a célula em cada linha da tabela para cada funcionário neste departamento! Na terceira forma normal, isso não teria acontecido.

Além disso, eis o que acontece se Mary decide sair da empresa: precisamos excluir sua linha da tabela, mas se ela era a única funcionária do departamento de operações, o departamento também precisará ser excluído.

Todos esses problemas podem ser completamente evitados em uma terceira forma normal.


Façanhas da mamãe . O nome da filha dela é Help! Eu sou forçado a passaportes falsos

2. Crie a última linha de defesa na forma de restrições


O banco de dados com o qual você está trabalhando é mais do que apenas um grupo de tabelas. Certas funcionalidades estão embutidas nele. Muitos desses recursos ajudam a garantir a qualidade e a precisão dos dados.

As restrições definem as regras, quais valores podem ser inseridos nos campos do banco de dados.

Ao definir relacionamentos em um banco de dados, certifique-se de definir restrições de chave estrangeira.

Certifique-se de especificar o que deve acontecer ao excluir e atualizar uma linha associada a outras linhas em outras tabelas (regras ON DELETE e ON UPDATE).

Certifique-se de usar NOT NULL para todos os campos que nunca devem ser anulados. Pode fazer sentido definir uma verificação no back-end, mas lembre-se de que as falhas sempre acontecem; portanto, adicionar esse tipo de restrição não será prejudicial.

Defina os limites de verificação CHECK para garantir que os valores da tabela estejam na faixa aceitável, por exemplo, o preço de um produto sempre tenha um valor positivo.

Um fato interessante : em abril de 2020, essa restrição de software impediu a negociação no MICEX de Moscou porque o preço dos futuros do petróleo WTI caiu abaixo de zero. Ao contrário da bolsa de valores de Moscou, a Bolsa Mercantil de Nova York NYMEX atualizou o software uma semana antes do incidente , para que pudesse realizar com êxito transações a um preço negativo, isto é, com uma sobretaxa ao comprador do vendedor - aprox. trans.

Todas as limitações do PostgreSQL podem ser encontradas aqui .

3. Nunca armazene endereços inteiros em um campo


Se o seu aplicativo ou site tiver um formulário com um campo em que o usuário digitar seu endereço, ele terá um cheiro ruim. É muito provável que, nesse caso, você também tenha um campo no banco de dados para armazenar o endereço como uma sequência simples.

Mas o que fazer se você precisar combinar compras de clientes por cidade para ver qual cidade é o produto mais popular? consegues fazê-lo?

Vai ser muito difícil!

Como o endereço completo é armazenado como uma sequência no campo do banco de dados, você primeiro precisa descobrir quanto dessa sequência é a cidade! E essa é uma tarefa quase impossível, considerando todos os formatos de endereço possíveis nesse campo.

Portanto, não se esqueça de dividir o campo universal "Endereço" em campos específicos: rua, número da casa, cidade, região, CEP e assim por diante.

Outro problema de endereço - campos anônimos


Aqui está uma ilustração do livro de Michaels Blach, A Bala de Cobre para Melhorar a Qualidade do Software:


Que problemas em potencial são visíveis aqui? Você consegue distinguir facilmente a cidade de Chicago das ruas de Chicago? Provavelmente não.

Portanto, lembre-se de sempre fornecer nomes de colunas claros para cada unidade de informação.


Como escrever um currículo

- Você tem experiência em SQL?

- Não (não)

- Então escreva: especialista NoSQL.

4. Nunca armazene o nome e o sobrenome em um campo


Semelhante à situação com endereços: o número de variações do nome e do sobrenome é muito grande para distinguir claramente entre eles.

Obviamente, você pode separar o nome do sobrenome, se houver um espaço entre eles.

Por exemplo, "Mike Alche" → o nome "Mike" e o sobrenome "Alche".

Mas e se o usuário digitar um nome do meio? Ou ele tem um sobrenome duplo? Mas e se houver um nome do meio e um sobrenome duplo?

Como determinar onde está o nome e onde está o sobrenome para dividir a string? Erros são inevitáveis.

Uma maneira de evitar muitos problemas é criar campos separados (em formulários) para os nomes de usuário first_name e last_name. Dessa forma, você permite que os usuários compartilhem seus próprios nomes e pode armazenar dados de maneira consistente.

Nota: Não estou dizendo que espaços são proibidos nos campos do banco de dados. Por exemplo, para nomes como Juan Martin Del Potro, a primeira parte de Juan Martin está no campo first_name e Del Potro está no campo last_name. Claro, isso não é perfeito . Opcionalmente, você pode ter as colunas middle_name e second_last_name. Veja com mais detalhes as possíveis variações de nomes e sobrenomes na lista “ Conceitos errôneos de programadores sobre nomes ” e no artigo “ Conceitos errôneos de programadores sobre nomes - com exemplos ”. Você precisa concordar com algum tipo de compromisso entre precisão e praticidade.

5. Defina convenções para nomes de tabelas e campos e atenha-se a eles


É muito chato trabalhar com dados que se parecem com user.firstName, user.lst_name, user.birthDate e assim por diante.

Eu recomendaria que você estabelecesse regras de nomeação de sublinhado, porque nem todos os mecanismos SQL lidam com letras maiúsculas da mesma maneira, e colocar tudo entre aspas é muito tedioso.

Escolha o mesmo que chamar as tabelas - no plural ou no singular (por exemplo, usuários no plural ou usuário no singular). Gosto mais do singular, mas todas as estruturas de back-end parecem plurais por padrão. Você tem que seguir o padrão e usar o plural.

O que mais se pode ler :

  1. Qual banco de dados escolher para o projeto, para que você não precise escolher novamente .
  2. IIoT-: Mail.ru Cloud Solutions .
  3. .

All Articles