Aula 4
4. Normalização do Esquema Relacional
4.1. Os Males da Redundância
Redundância é a causa de vários
problemas com esquemas relacionais:
-
armazenamento redundante, anomalias de inserção,
de exclusão e de atualização.
Restrições de integridade, particularmente
dependências funcionais, podem ser usadas para identificar esquemas
com esses problemas e para sugerir refinamentos.
Principal técnica de refinamento:
a decomposição de um esquema em sub-esquemas.
A decomposição deve ser usada
judiciosamente:
-
Há motivos para se decompor uma relação?
-
A decomposição pode causar problemas?
Considere o esquema:
-
Pacientes(Id, Nome, Endereço,
Telefone, Sexo, Data_nascimento, Sigla_convênio, Nome_convênio,
Endereço_convênio, Telefone_convênio)
Esse é um exemplo de mau projeto!
-
Os dados de pacientes e os de convênios
não deveriam estar na mesma tabela.
Por que?
-
Os dados de um convênio (nome, endereço
e telefone do convênio) são repetidos para cada paciente associado
a esse convênio. Por exemplo, os dados da AMIL serão repetidos
para cada um de seus associados.
Anomalia de inserção:
-
Quando se inserir um paciente é preciso
inserir também os dados do convênio, mesmo que já estejam
cadastrados.
-
Não é possível inserir
um convênio sem inserir também um paciente.
Anomalia de exclusão:
-
Ao se excluir um paciente, se este for o único
associado de um convênio então os dados do convênio
serão perdidos.
Anomalia de modificação:
-
Para se modificar os dados de um convênio,
é preciso atualizar os mesmos dados em todas as tuplas de pacientes
que estejam associados àquele convênio.
4.2. Dependências
Funcionais
Dependências funcionais (DFs) são
restrições de integridade mais gerais que as restrições
de chave.
Exemplo de dependência funcional:
{Sigla_convênio}
-> {Nome_convênio, Endereço_convênio,
Telefone_convênio}
-
Leia-se: Sigla_convênio determina funcionalmente
Nome_convênio, Endereço_convênio e Telefone_convênio.
-
Significado: “Se duas linhas da tabela Pacientes
tiverem o mesmo valor de Sigla_convênio, então elas tem de
ter o mesmo valor de Nome_convênio, de Endereço_convênio
e de Telefone_convênio.”
-
Em outras palavras: “Não é válida
uma tabela que tenha duas linhas que coincidem na(s) coluna(s) listadas
antes da seta (->), mas são diferentes em alguma coluna listada
depois da seta.”
Como toda restrição de integridade,
DFs são baseadas na semântica da aplicação.
-
Podemos checar uma instância de tabela
e ver se uma DF é violada ou não. Mas examinando uma instância
NUNCA podemos concluir uma DF deve ser imposta ou não.
-
Uma DF diz respeito a todas as possíveis
instâncias!
Uma restrição de chave é
um caso especial de DF: a chave (ou superchave) determina funcionalmente
todos os outros atributos da tabela.
-
Como Id é chave da tabela Pacientes,
temos que
{Id} ->
{Nome, Endereço, Telefone, Sexo, Data_nascimento, Sigla_convênio,
Nome_convênio, Endereço_convênio, Telefone_convênio}
4.3. Inferindo DFs
Dadas algumas DFs, podemos geralmente inferir
outras.
Dadas as DFs:
{Id} ->
{Sigla_convênio}
{Sigla_convênio}
-> {Endereço_convênio}
podemos inferir que:
{Id} ->
{Endereço_convênio}
Regras de inferência (X, Y e Z são
conjuntos de atributos):
-
Reflexividade: Se Y está contido em
X então X -> Y.
-
Aumentação: Se X -> Y, então
XZ -> YZ.
-
Transitividade: Se X -> Y e Y -> Z então
X -> Z.
-
União: Se X -> Y e X -> Z então
X -> YZ.
-
Decomposição: Se X -> YZ então
X -> Y e X -> Z.
4.4. Fecho de um conjunto
de DFs
O fecho (closure) de um conjunto de dependências
funcionais F é o conjunto de todas as DFs que podem ser inferidas
a partir de F.
Não é preciso listar todas
as DFs impostas sobre um esquema. Normalmente especificarmos um subconjunto
dessas DFs e considerarmos o fecho desse subconjunto.
-
Para o esquema Pacientes, é suficiente
especificarmos as DFs:
{Id} -> {Nome, Endereço,
Telefone, Sexo, Data_nascimento, Sigla_convênio}
{Sigla_convênio}
-> {Nome_convênio, Endereço_convênio, Telefone_convênio}
O fecho inclui dependências funcionais
triviais (aquelas que são satisfeitas por todas as instâncias
de tabela possíveis).
-
As dependências triviais tem a forma
X -> Y, onde Y está contido em X.
-
Exemplos:
-
{Nome, Endereço} -> {Nome}
-
{Nome} -> {Nome}
4.5. Formas Normais
Certas DFs causam redundância!
-
Para cada associado de um convênio,
os dados do convênio são repetidos na tabela Pacientes. A
causa desse problema é a DF
{Sigla_convênio}
-> {Nome_convênio, Endereço_convênio, Telefone_convênio}
Se uma relação estiver numa
certa forma normal (FNBC ou 3FN), tais problemas são evitados ou
minimizados.
-
Essas formas normais são definidas
em termos de dependências funcionais.
-
Elas nos fornecem critérios para decidir
o esquema de uma relação deve ser decomposto em sub-esquemas
ou não.
-
Existem várias formas normais: 2FN,
3FN, FNBC, 4FN.
Estudaremos as que têm importância
prática (FNBC e 3FN).
4.6. Forma Normal de Boyce-Codd
Uma relação está na
FNBC (BCNF) se todas as suas dependências funcionais não triviais
forem da forma
superchave -> conjunto-de-atributos
Em outras palavras: além das dependências
funcionais triviais, só podemos ter restrições de
chave.
Uma relação na FNBC está
livre de redundâncias que podem ser detetadas usando DFs.
O esquema Pacientes não está
na FNBC: a dependência funcional
{Sigla_convênio}
-> {Nome_convênio, Endereço_convênio, Telefone_convênio}
é uma violação da FNBC,
pois Sigla_convênio não é chave.
Decompomos Pacientes nas duas relações
abaixo.
Pacientes1(Id,
Nome, Endereço, Telefone, Sexo, Data_nascimento, Sigla_convênio)
Convênio(Sigla_convênio,
Nome_convênio, Endereço_convênio, Telefone_convênio)
-
Essas relações estão
na FNBC com respeito ao conjunto de DFs
{Id} -> {Nome, Endereço,
Telefone, Sexo, Data_nascimento, Sigla_convênio}
{Sigla_convênio}
-> {Nome_convênio, Endereço_convênio, Telefone_convênio}
-
Agora a segunda dependência funcional
não viola a FNBC, pois Sigla_convênio é chave de Convênios.
Essa decomposição elimina a
redundância do esquema original Pacientes.
4.7. Problemas com Decomposições
Três problemas potenciais devem ser
considerados:
-
Certas consultas requerem mais processamento
(junções).
-
Exemplo: Qual o telefone do convênio
do paciente José da Silva?
-
Perda de informação: Dadas instâncias
das tabelas decompostas, pode não ser possível reconstruirmos
a instância correspondente da tabela original!
-
Isso é inaceitável e não
acontece no caso de nosso exemplo.
-
Custo de verificação de dependências:
Para verificar se uma dependência é satisfeita pode ser preciso
efetuar junções das tabelas decompostas (a verificação
dessa dependência é custosa).
-
Geralmente inaceitável, não
acontece no caso de nosso exemplo.
4.8. Decomposição
sem perdas
Uma decomposição é
sem perdas se for sempre possível reconstruir a instância
da tabela original efetuando a junção das instâncias
correspondentes das tabelas decompostas.
Exemplo de decomposição com
perdas:

A decomposição de um esquema
R em sub-esquemas X e Y é sem perdas se e somente se pelo menos
uma das duas DFs abaixo valer:
X intersecção
Y -> X, ou X intersecção Y -> Y.
-
Caso especial: se valer a dependência
U -> V, então a decomposição de R em UV e R - V é
sem perdas.
-
Verifique que a decomposição
de Pacientes satisfaz esta condição!
4.9. Algoritmo de decomposição
da FNBC
Considere uma relação R e
as DFs associadas a ela. Se X -> Y violar a FNBC, decomponha R em XY e
R - Y.
-
Aplicando esta idéia repetidamente,
obteremos uma decomposição sem perdas de R em uma coleção
de relações na FNBC.
-
Em geral, mais de uma DF pode violar a FNBC.
Dependendo da ordem com que usarmos as dependências violadoras, podemos
obter decomposições diferentes (e mesmo assim corretas).
Exemplo: o esquema
Empréstimos1(Nome_agência,
Ativos, Cidade_agência, Num_empréstimo, Nome_cliente,
Quantia)
e as DFs
{Nome_agência} ->
{Ativos, Cidade_agência}
{Num_empréstimo}
-> {Quantia, Nome_agência}
-
Note que {Num_empréstimo, Nome_cliente}
é a única chave.
Empréstimos1(Nome_agência,
Ativos, Cidade_agência, Num_empréstimo, Nome_cliente, Quantia)
1 {Nome_agência}
-> {Ativos, Cidade_agência}
2 {Num_empréstimo}
-> {Quantia, Nome_agência}
A DF 1 viola a FNBC, pois Nome_agência
não é superchave de Empréstimos1. Portanto decompomos
essa tabela em
Agências(Nome_agência,
Ativos, Cidade_agência)
Empréstimos2(Nome_agência,
Num_empréstimo, Nome_cliente, Quantia)
A DF 2 viola a FNBC, pois Num_empréstimo
não é superchave de Empréstimos2. Portanto decompomos
essa tabela em
Empréstimos(Num_empréstimo,
Nome_agência, Quantia)
Tomadores(Num_empréstimo,
Nome_cliente)
-
Resultado: 3 tabelas (Agências, Empréstimos
e Tomadores).
4.10. Preservação
de dependências
Considere o esquema e as DFs:
Gerentes(Nome_agência,
Nome_cliente, Nome_gerente)
1 {Nome_gerente} -> {Nome_agência}
2 {Nome_cliente, Nome_agência}
-> {Nome_gerente}
(Cada cliente de uma
agência tem um “gerente pessoal” na agência.)
Uma decomposição FNBC é:
Gerentes_agências(Nome_gerente,
Nome_agência)
Gerentes_clientes(Nome_cliente,
Nome_gerente)
Problema: É necessário fazer
uma junção para verificar se a segunda DF é violada
ou não.
-
Inaceitável! Teríamos que fazer
uma junção após cada atualização dessas
tabelas, apenas para assegurarmos que a DF 2 é cumprida.
Decomposição com preservação
de dependências:
-
Considere uma relação R e as
DFs associadas a ela, bem como uma decomposição de R em R1,
R2, …, Rn. Se, para cada Ri, assegurarmos que as DFs aplicáveis
a Ri (aquelas que envolvem somente atributos de Ri) estão satisfeitas,
então podemos ter certeza que todas as DFs associadas a R estão
satisfeitas.
Nossa decomposição FNBC da tabela
Gerentes não tem esta propriedade.
-
A dependência {Nome_cliente,
Nome_agência} -> {Nome_gerente} foi “perdida”.
É importante considerar o fecho do
conjunto de DFs!
-
Exemplo: R(A,B,C), com DFs {A} -> {B}, {B}
-> {C} e {C} -> {A}.
-
A decomposição de R em (A,B)
e (B,C) é com preservação de dependências? A
terceira DF é preservada ou não?
4.11. Terceira Forma Normal
(3FN)
Uma relação R está
na 3FN (3NF) se cada uma de suas dependências funcionais da forma
X -> A cair num dos casos abaixo:
(Aqui X é um
conjunto de atributos e A é um atributo simples.)
1) A esta contido em X (isto é,
a DF é trivial), ou
2) X é uma superchave de R, ou
3) A faz parte de alguma chave de R (A
é um atributo primo).
Em outras palavras: além das DFs
triviais, só podemos ter restrições de chave ou dependências
da forma
conjunto-de-atributos -> atributo-primo
-
A 3FN é uma forma normal mais fraca
(menos restritiva) que a FNBC. Toda relação que estiver na
FNBC estará também na 3FN, mas a recíproca não
é verdadeira.
Considere novamente o exemplo do “gerente
pessoal”:
Gerentes(Nome_agência,
Nome_cliente, Nome_gerente)
1 {Nome_gerente} -> {Nome_agência}
2 {Nome_cliente, Nome_agência}
-> {Nome_gerente}
A tabela tem as seguintes chaves candidatas:
{Nome_cliente, Nome_agência}
{Nome_cliente, Nome_gerente}
(Todos os atributos
são primos!)
-
Essa tabela não está na FNBC,
mas está na 3FN!
-
A DF 1 é uma violação
da FNBC, pois Nome_gerente não é chave.
-
Ela não viola a 3FN, pois Nome_agência
é um atributo primo.
-
Note que a tabela Gerentes não está
livre de problemas de redundância.
-
A associação entre um gerente
e sua agência é repetida para cada cliente desse gerente.
4.12. FNBC ou 3FN
A FNBC nos assegura que uma relação
está livre de redundâncias detectáveis através
de DFs.
Com a 3FN, alguma redundância ainda
é possível.
-
A 3FN é uma solução de
compromisso!
Dada uma relação que não
está na FNBC, nem sempre é possível conseguirmos uma
decomposição FNBC que seja sem perdas e com preservação
de dependências.
-
Se insistirmos numa decomposição
FNBC, poderemos ter que abrir mão da preservação de
dependências.
-
Mas é sempre possível uma decomposição
3FN que seja sem perdas e com preservação de dependências.
Nos casos (raros) em que for necessário
optar entre a FNBC e a preservação de dependências,
ficamos com a preservação de dependências e com uma
forma normal mais fraca, a 3FN.
4.13. Conclusões
Como a FNBC nos garante que não
temos redundância detectável através de DFs, devemos
considerar essa forma normal como um objetivo desejável do projeto
lógico.
Se uma relação não
estiver na FNBC, podemos tentar decompô-la num coleção
de relações na FNBC.
-
A decomposição deve ser sem
perdas e com preservação de dependências.
-
Se isso não for possível, considerar
decomposição na 3FN.
Lembrar que a decomposição tem
um custo (junções).
-
Não assuma a postura rígida,
dogmática, de normalizar a todo custo!
-
Decomposições devem ser efetuadas
e reexaminadas tendo em mente os requisitos de desempenho da aplicação.
[voltar]
|