Normalização

O design lógico do banco de dados, inclusive as tabelas e as relações entre elas, é a parte fundamental de um banco de dados relacional otimizado. Um bom design lógico de banco de dados pode tornar-se o alicerce de um ótimo desempenho dos bancos de dados e dos aplicativos. Um design lógico de banco de dados precário pode comprometer o desempenho do sistema inteiro.

A normalização do design lógico de um banco de dados envolve o uso de métodos formais para separar os dados em várias tabelas relacionadas. Várias tabelas estreitas com menos colunas são características de um banco de dados normalizado. Poucas tabelas largas com mais colunas são características de um banco de dados não normalizado.

Muitas vezes, uma normalização razoável melhora o desempenho. Quando índices úteis estiverem disponíveis, o otimizador de consulta SQL Server é eficiente para selecionar junções rápidas e eficazes entre as tabelas.

Alguns benefícios da normalização incluem o seguinte:

  • Classificação e criação mais rápidas dos índices.

  • Um número maior de índices cluster. Para obter mais informações, consulte Diretrizes de design de índices clusterizados.

  • Índices mais estreitos e mais compactados.

  • Menos índices por tabela. Isto melhora o desempenho das instruções INSERT, UPDATE e DELETE.

  • Menos valores nulos e menos oportunidades de inconsistências. Isto aumenta a densidade do banco de dados.

Conforme a normalização aumenta, o número e a complexidade das junções, necessários para a recuperação de dados, também aumentam. Muitas junções relacionais complexas entre várias tabelas podem comprometer o desempenho. Frequentemente, uma normalização razoável inclui poucas consultas normalmente executadas que usam junções envolvendo mais de quatro tabelas.

Às vezes, o design lógico do banco de dados já está fixado e um novo design geral não é realístico. Porém, mesmo assim, é possível normalizar seletivamente uma grande tabela em várias tabelas menores. Se o banco de dados for acessado por meio de procedimentos armazenados, essa alteração de esquema poderá acontecer sem afetar os aplicativos. Caso contrário será possível criar uma exibição que oculte a alteração de esquema dos aplicativos.

Desenvolvendo um banco de dados bem projetado

Em teoria de design de banco de dados relacional, as regras de normalização identificam alguns atributos que devem estar presentes ou ausentes em um banco de dados bem projetado. Uma abordagem completa das regras de normalização excede o escopo deste tópico. Porém, há algumas regras que podem ajudar a obter um design de banco de dados satisfatório:

  • Uma tabela deverá ter um identificador.

    A regra fundamental da teoria do design de banco de dados é que cada tabela deverá ter um identificador de linha exclusivo, uma coluna ou um conjunto de colunas para diferenciar um único registro dos demais registros na tabela. Cada tabela deverá ter uma coluna de ID e dois registros não poderão compartilhar o mesmo valor de ID. A coluna ou as colunas que servem como identificador de linha exclusivo para uma tabela são as chaves primárias da tabela. No banco de dados AdventureWorks2008R2, cada tabela contém uma coluna de identidade como coluna de chave primária. Por exemplo, VendorID é chave primária para a tabela Purchasing.Vendor.

  • Uma tabela só deve armazenar dados para um único tipo de entidade.

    Tentar armazenar muitas informações em uma tabela poderá comprometer o gerenciamento eficiente e confiável dos dados na tabela. No banco de dados de exemplo AdventureWorks2008R2, o pedido de vendas e as informações do cliente estão armazenados em tabelas separadas. Embora seja possível ter colunas com informações do pedido de vendas e do cliente em uma única tabela, esse design poderá apresentar vários problemas. As informações de cliente, nome e endereço, devem ser adicionadas e armazenadas de forma redundante para cada pedido de vendas. Isto usa espaço de armazenamento adicional no banco de dados. Se o endereço do cliente for alterado, a alteração deverá ser realizada para cada pedido de vendas. Além disso, se o último pedido de vendas para um cliente for removido da tabela Sales.SalesOrderHeader, as informações para aquele cliente serão perdidas.

  • Uma tabela deve evitar colunas que permitem valor nulo.

    As tabelas podem ter colunas definidas para permitir valores nulos. Um valor nulo indica que não há nenhum valor. Embora seja útil permitir valores nulos em casos isolados, você deverá usa-los esporadicamente. Isto é porque eles requerem um tratamento especial que aumente a complexidade das operações de dados. Se tiver uma tabela com várias colunas que permitem valor nulo e várias linhas tiverem valores nulos nas colunas, você deverá considerar a colocação dessas colunas em outra tabela vinculada à tabela principal. Armazenando os dados em duas tabelas separadas, a tabela principal poderá ter um design simples e, mesmo assim, tratar da necessidade ocasional de armazenamento dessas informações.

  • Uma tabela não deverá ter valores ou colunas repetitivos.

    A tabela para um item do banco de dados não deve conter uma lista de valores para uma parte específica de informações. Por exemplo, um produto no banco de dados do AdventureWorks2008R2 pode ser adquirido de vários fornecedores. Se houver uma coluna na tabela Production.Product para o nome do fornecedor, isso resultará em um problema. Uma solução seria armazenar o nome de todos os fornecedores na coluna. Porém, isto torna difícil a exibição de uma lista dos fornecedores individuais. Uma outra solução seria alterar a estrutura da tabela para adicionar mais uma coluna para o nome do segundo fornecedor. Porém, isto permitirá apenas dois fornecedores. Além disso, uma outra coluna deverá ser adicionada se o livro tiver três fornecedores.

    Se achar que deve armazenar uma lista de valores em uma única coluna, ou se tiver várias colunas para uma única parte dos dados, como o TelephoneNumber1 e TelephoneNumber2, você deverá considerar a colocação dos dados duplicados em outra tabela com um vínculo de volta para a tabela principal. O banco de dados AdventureWorks2008R2 tem uma tabela Production.Product para as informações do produto, uma tabela Purchasing.Vendor para as informações do fornecedor e uma terceira tabela Purchasing.ProductVendor. Essa terceira tabela armazena somente os valores de ID dos produtos e os IDs dos fornecedores desses produtos. Esse design permite um número de fornecedores para um produto sem modificar a definição das tabelas e sem alocação de espaço de armazenamento inutilizado para produtos com um único fornecedor.