Há algum tempo em que usar um relacionamento de database 1: 1 faz sentido?

Eu estava pensando outro dia sobre normalização, e me ocorreu, não consigo pensar em um momento em que deveria haver um relacionamento 1: 1 em um database.

Nome: SSN Eu os teria na mesma tabela PersonID: AddressID? Mais uma vez, a mesma tabela.

Eu posso chegar a um zilhão de exemplos de 1: muitos ou muitos: muitos (com tabelas intermediárias apropriadas), mas nunca 1: 1.

Estou faltando alguma coisa óbvia?

Um relacionamento 1: 1 geralmente indica que você particionou uma entidade maior por algum motivo. Muitas vezes, é por causa de razões de desempenho no esquema físico, mas isso pode acontecer no lado lógico, bem como se espera que uma grande parte dos dados seja “desconhecida” ao mesmo tempo (nesse caso, você tem 1: 0 ou 1: 1, mas não mais).

Como exemplo de uma partição lógica: você tem dados sobre um funcionário, mas há um conjunto maior de dados que precisam ser coletados, se e somente se eles optarem por ter cobertura de saúde. Eu manteria os dados democharts em relação à cobertura de saúde em uma tabela diferente para facilitar o particionamento de segurança e evitar transportar esses dados em consultas não relacionadas ao seguro.

Um exemplo de uma partição física seria o mesmo dado sendo hospedado em vários servidores. Posso manter os dados democharts de cobertura de saúde em outro estado (onde o escritório de RH é, por exemplo) e o database principal só pode vincular a ele por meio de um servidor vinculado … evitando replicar dados confidenciais para outros locais, tornando-os disponíveis para (supondo aqui raro) consultas que precisam dele.

O particionamento físico pode ser útil sempre que você tiver consultas que precisem de subconjuntos consistentes de uma entidade maior.

Um dos motivos é a eficiência do database. Ter um relacionamento 1: 1 permite dividir os campos que serão afetados durante um bloqueio de linha / tabela. Se a tabela A tem uma tonelada de atualizações e a tabela b tem uma tonelada de leituras (ou tem uma tonelada de atualizações de outro aplicativo), então o bloqueio da tabela A não afetará o que está acontecendo na tabela B.

Outros trazem um bom ponto. A segurança também pode ser uma boa razão, dependendo de como os aplicativos, etc., estão atingindo o sistema. Eu tenderia a ter uma abordagem diferente, mas pode ser uma maneira fácil de restringir o access a determinados dados. É muito fácil simplesmente negar o access a uma determinada tabela em um piscar de olhos.

Minha input no blog sobre isso.

Sparseness. O relacionamento de dados pode ser tecnicamente 1: 1, mas linhas correspondentes não precisam existir para cada linha. Portanto, se você tiver 20 milhões de linhas e houver um conjunto de valores que só existe para 0,5% deles, a economia de espaço será grande se você colocar essas colunas em uma tabela que pode ser pouco preenchida.

Eu os uso principalmente por alguns motivos. Uma é a diferença significativa na taxa de mudança de dados. Algumas de minhas tabelas podem ter trilhas de auditoria nas quais eu rastreio versões anteriores de registros, se eu apenas me importar em acompanhar versões anteriores de 5 de 10 colunas dividindo essas 5 colunas em uma tabela separada com um mecanismo de trilha de auditoria mais eficiente. Além disso, eu posso ter registros (digamos, para um aplicativo de contabilidade) que são somente para gravação. Você não pode alterar os valores em dólar ou a conta em que estavam, se tiver cometido um erro, precisará fazer um registro correspondente para gravar o registro incorreto e criar uma input de correção. Eu tenho restrições na tabela impondo o fato de que elas não podem ser atualizadas ou excluídas, mas posso ter alguns atributos para esse object que são maleáveis, que são mantidos em uma tabela separada sem a restrição de modificação. Outra vez que faço isso é em aplicações de registros médicos. Há dados relacionados a uma visita que não podem ser alterados depois de assinados e outros dados relacionados a uma visita que podem ser alterados após a aprovação. Nesse caso, vou dividir os dados e colocar um gatilho na tabela bloqueada rejeitando as atualizações para a tabela bloqueada quando assinadas, mas permitindo atualizações nos dados que o médico não está assinando.

Outro pôster comentou sobre o 1: 1 não estar normalizado, eu discordaria disso em algumas situações, especialmente na subtipagem. Digamos que eu tenha uma tabela de funcionários e a chave primária seja o SSN (é um exemplo, vamos salvar o debate sobre se essa é uma boa chave ou não para outro segmento). Os funcionários podem ser de tipos diferentes, digamos temporários ou permanentes e, se forem permanentes, têm mais campos a serem preenchidos, como o número de telefone do escritório, que não deve ser nulo se o tipo = ‘Permanente’. Em um database de formulário normal, a coluna deve depender apenas da chave, ou seja, do funcionário, mas na verdade depende do funcionário e do tipo, portanto, um relacionamento de 1: 1 é perfeitamente normal e desejável nesse caso. Ele também evita tabelas excessivamente esparsas, se eu tiver 10 colunas que normalmente são preenchidas, mas 20 colunas adicionais somente para determinados tipos.

Sua pergunta pode ser interpretada de várias maneiras, devido à maneira como você a redigiu. As respostas mostram isso.

Definitivamente, pode haver relacionamentos 1: 1 entre itens de dados no mundo real. Nenhuma pergunta sobre isso. O relacionamento “é um” é geralmente de um para um. Um carro é um veículo. Um carro é um veículo. Um veículo pode ser um carro. Alguns veículos são caminhões, caso em que um veículo não é um carro. Várias respostas abordam essa interpretação.

Mas eu acho que o que você está realmente perguntando é … quando existem relacionamentos 1: 1, as tabelas deveriam ser divididas? Em outras palavras, você deveria ter duas tabelas que contenham exatamente as mesmas chaves? Na prática, a maioria de nós analisa apenas as chaves primárias, e não outras chaves candidatas, mas essa questão é ligeiramente diferente.

As regras de normalização para 1NF, 2NF e 3NF nunca exigem a decomposição (divisão) de uma tabela em duas tabelas com a mesma chave primária. Eu não tenho trabalhado se colocar um esquema em BCNF, 4NF ou 5NF pode resultar em duas tabelas com as mesmas chaves. No topo da minha cabeça, eu vou adivinhar que a resposta é não.

Existe um nível de normalização chamado 6NF. A regra de normalização para 6NF pode resultar em duas tabelas com a mesma chave primária. 6NF tem a vantagem sobre 5NF que NULLS pode ser completamente evitado. Isso é importante para alguns, mas não todos, designers de database. Eu nunca me preocupei em colocar um esquema no 6NF.

Em 6NF, os dados perdidos podem ser representados por uma linha omitida, em vez de uma linha com um NULL em alguma coluna.

Existem outras razões além da normalização para dividir as tabelas. Às vezes, as tabelas divididas resultam em melhor desempenho. Com alguns mecanismos de database, você pode obter os mesmos benefícios de desempenho particionando a tabela em vez de dividi-la. Isso pode ter a vantagem de manter o design lógico fácil de entender, enquanto fornece ao mecanismo de database as ferramentas necessárias para acelerar as coisas.

A maioria das respostas altamente ranqueadas fornece razões de otimização e ajuste de database muito úteis para relacionamentos 1: 1, mas eu quero focar apenas em exemplos “em estado selvagem” onde relações 1: 1 ocorrem naturalmente.

Observe uma característica importante da implementação do database da maioria desses exemplos: nenhuma informação histórica é retida sobre o relacionamento 1: 1. Ou seja, esses relacionamentos são 1: 1 em qualquer ponto no tempo. Se o designer de database quiser registrar mudanças nos participantes do relacionamento ao longo do tempo, os relacionamentos se tornarão 1: M ou M: M; eles perdem sua natureza 1: 1. Com isso entendido, aqui vai:

  • Relacionamentos “Is-A” ou supertipo / subtipo ou inheritance / sorting : essa categoria é quando uma entidade é um tipo específico de outra entidade. Por exemplo, pode haver uma entidade Employee com atributos que se aplicam a todos os funcionários e entidades diferentes para indicar tipos específicos de funcionários com atributos exclusivos para esse tipo de funcionário, por exemplo, Doctor, Accountant, Pilot etc. Esse design evita vários nulos desde muitos funcionários não teriam os atributos especializados de um subtipo específico. Outros exemplos nesta categoria podem ser Product como supertipo e ManufacturingProduct e MaintenanceSupply como subtipos; Animal como supertipo e Cão e Gato como subtipos; Observe que sempre que você tentar mapear uma hierarquia de inheritance orientada a objects em um database relacional (como em um modelo relacional de object), esse é o tipo de relacionamento que representa esses cenários.

  • Relacionamentos de “chefe” , como gerente, presidente, presidente, etc., em que uma unidade organizacional pode ter apenas um chefe e uma pessoa pode ser chefe de apenas uma unidade organizacional. Se essas regras se aplicarem, então você tem um relacionamento de 1: 1, como um gerente de departamento, um CEO de uma empresa, etc. Os relacionamentos de “chefe” não se aplicam apenas a pessoas. O mesmo tipo de relacionamento ocorre se houver apenas uma loja como sede de uma empresa, ou se apenas uma cidade for a capital de um país, por exemplo.

  • Alguns tipos de alocação de resources escassos , por exemplo, um empregado pode ser atribuído apenas um carro da empresa de cada vez (por exemplo, um caminhão por caminhoneiro, um táxi por motorista de táxi, etc.). Um colega me deu esse exemplo recentemente.

  • Casamento (pelo menos em jurisdições legais onde a poligamia é ilegal): uma pessoa pode ser casada com apenas uma outra pessoa de cada vez. Eu obtive este exemplo de um livro que usou isso como um exemplo de um relacionamento unário 1: 1 quando uma empresa registra casamentos entre seus funcionários.

  • Reservas correspondentes : quando uma reserva única é feita e, em seguida, preenchida como duas entidades separadas. Por exemplo, um sistema de aluguel de carros pode registrar uma reserva em uma entidade e, em seguida, uma locação real em uma entidade separada. Embora tal situação possa, alternativamente, ser projetada como uma entidade, pode fazer sentido separar as entidades, uma vez que nem todas as reservas são atendidas, e nem todas as locações exigem reservas, e ambas as situações são muito comuns.

Repito a ressalva que fiz anteriormente de que a maioria deles é de relações 1: 1 somente se nenhuma informação histórica for registrada. Assim, se um funcionário mudar de function em uma organização, ou um gerente assumir a responsabilidade de um departamento diferente, ou um funcionário for transferido de um veículo, ou alguém estiver viúvo e voltar a se casar, os participantes do relacionamento poderão mudar. Se o database não armazenar nenhum histórico anterior sobre esses relacionamentos 1: 1, eles permanecerão legítimos como relacionamentos 1: 1. Mas se o database registra informações históricas (como adicionar datas de início e término para cada relacionamento), elas praticamente se transformam em relacionamentos M: M.

Há duas notáveis ​​exceções à nota histórica: Primeiro, alguns relacionamentos mudam tão raramente que informações históricas normalmente não seriam armazenadas. Por exemplo, a maioria das relações IS-A (por exemplo, tipo de produto) é imutável; isto é, eles nunca podem mudar. Assim, o registro histórico é irrelevante; estes seriam sempre implementados como relacionamentos naturais de 1: 1. Em segundo lugar, a loja de relacionamento reserva-aluguel é separada separadamente, uma vez que a reserva e a locação são events independentes, cada um com suas próprias datas. Como as entidades têm suas próprias datas, em vez de o próprio relacionamento 1: 1 ter uma data de início, elas permaneceriam como relacionamentos 1: 1, mesmo que as informações históricas sejam armazenadas.

O cenário mais comum em que consigo pensar é quando você tem BLOBs. Digamos que você queira armazenar imagens grandes em um database (normalmente, não a melhor maneira de armazená-las, mas às vezes as restrições tornam isso mais conveniente). Normalmente, você deseja que o blob esteja em uma tabela separada para melhorar as pesquisas dos dados não-blob.

Em termos de ciência pura, sim, eles são inúteis.

Em bancos de dados reais, às vezes é útil manter um campo raramente usado em uma tabela separada: para acelerar as consultas usando esse e somente esse campo; para evitar bloqueios, etc.

Em vez de usar modos de exibição para restringir o access a campos, às vezes faz sentido manter campos restritos em uma tabela separada à qual apenas determinados usuários têm access.

Também posso pensar em situações em que você tem um modelo OO no qual você usa inheritance e a tree de inheritance deve ser persistida no database.

Por exemplo, você tem uma class Bird and Fish, que herda de Animal. No seu database você poderia ter uma tabela ‘Animal’, que contém os campos comuns da class Animal, e a tabela Animal tem um relacionamento um-para-um com a tabela Bird e um relacionamento um-para-um com o Fish mesa.

Neste caso, você não precisa ter uma tabela Animal que contenha muitas colunas anuláveis ​​para armazenar as propriedades Bird e Fish, onde todas as colunas que contêm Fish-data são definidas como NULL quando o registro representa um pássaro.

Em vez disso, você tem um registro na tabela de aves que tem um relacionamento um-para-um com o registro na tabela Animal.

1-1 relacionamentos também são necessários se você tiver muita informação. Há uma limitação de tamanho de registro em cada registro na tabela. Às vezes, as tabelas são divididas em duas (com as informações mais comumente consultadas na tabela principal) apenas para que o tamanho do registro não seja muito grande. Bancos de dados também são mais eficientes em consultar se as tabelas são estreitas.

É também uma maneira de estender uma tabela que já está em produção com menos risco (percebido) do que uma mudança de database “real”. Ver um relacionamento 1: 1 em um sistema legado é geralmente um bom indicador de que os campos foram adicionados após o design inicial.

Se você estiver usando os dados com um dos ORMs populares, convém dividir uma tabela em várias tabelas para corresponder à sua hierarquia de objects.

Descobri que, quando faço uma relação de 1: 1, é totalmente por uma razão sistêmica, não uma razão relacional.

Por exemplo, descobri que colocar os aspectos reservados de um usuário em uma tabela e colocar os campos editáveis ​​do usuário em uma tabela diferente permite escrever logicamente essas regras sobre as permissions nesses campos de maneira muito mais fácil.

Mas você está correto, em teoria, os relacionamentos 1: 1 são completamente inventados e são quase um fenômeno. No entanto, logicamente, permite que os programas e otimizações que abstraem o database sejam mais fáceis.

No SQL, é impossível impor um relacionamento 1: 1 entre duas tabelas que é obrigatório em ambos os lados (a menos que as tabelas sejam somente leitura). Para propósitos mais práticos, um relacionamento “1: 1” em SQL realmente significa 1: 0 | 1.

A incapacidade de suportar cardinalidade obrigatória em restrições referenciais é uma das sérias limitações do SQL. As restrições “Deferráveis” não contam realmente porque são apenas uma maneira de dizer que a restrição não é aplicada em parte do tempo.

Na maioria das vezes, acredita-se que os designs sejam 1: 1 até que alguém pergunte “bem, por que não pode ser 1: muitos”? Divorciando os conceitos uns dos outros prematuramente é feito em antecipação a este cenário comum. Pessoa e endereço não se ligam tão bem. Muitas pessoas têm vários endereços. E assim por diante…

Normalmente, dois espaços de objects separados implicam que um ou ambos podem ser multiplicados (x: muitos). Se dois objects eram verdadeiramente, verdadeiramente 1: 1, até filosoficamente, então é mais um relacionamento-é. Esses dois “objects” são, na verdade, partes de um object inteiro.

informações estendidas que são necessárias apenas em determinados cenários. em aplicativos legados e linguagens de programação (como RPG), onde os programas são compilados sobre as tabelas (portanto, se a tabela for alterada, você terá que recompilar o (s) programa (s)). Arquivos tag along também podem ser úteis nos casos em que você precisa se preocupar com o tamanho da tabela.

Mais frequentemente, é mais uma construção física do que lógica. É comumente usado para particionar verticalmente uma tabela para aproveitar a divisão de E / S em dispositivos físicos ou outras otimizações de consulta associadas à segregação de dados ou dados acessados ​​com menos frequência que precisam ser mantidos mais seguros que o restante dos atributos no mesmo object (SSN, salário, etc).

A única consideração lógica que prescreve um relacionamento 1-1 é quando determinados atributos se aplicam apenas a algumas das entidades. No entanto, na maioria dos casos, existe uma maneira melhor / mais normalizada de modelar os dados por meio da extração de entidades.

A melhor razão que eu posso ver para um relacionamento 1: 1 é um SubType SuperType de design de database. Eu criei uma estrutura de dados MLS para imóveis com base nesse modelo. Havia cinco feeds de dados diferentes; Residencial, Comercial, MultiFamily, Hotéis e Terrenos.

Eu criei uma SuperType chamada propriedade que continha dados que eram comuns a cada um dos cinco feeds de dados separados. Isso permitiu pesquisas “simples” muito rápidas em todos os tipos de dados.

Eu crio cinco SubTypes separados que armazenam os elementos de dados exclusivos para cada um dos cinco feeds de dados. Cada registro SuperType tinha um relacionamento 1: 1 com o registro SubType apropriado.

Se um cliente quisesse uma pesquisa detalhada, teria que selecionar um tipo Super-Sub, por exemplo, PropertyResidential.

Na minha opinião, um relacionamento 1: 1 mapeia uma inheritance de class em um RDBMS. Existe uma tabela A que contém os atributos comuns, isto é, o status da class partent Cada status de class herdada é mapeado no RDBMS com uma tabela B com um relacionamento 1: 1 para uma tabela, contendo os atributos especializados. A tabela namend A contém também um campo “type” que representa a funcionalidade “casting”

Tchau Mario

Relacionamentos 1: 1 realmente não fazem sentido se você estiver em normalização, pois qualquer coisa que seria 1: 1 seria mantida na mesma mesa.

No mundo real, muitas vezes é diferente. Você pode querer dividir seus dados para corresponder à sua interface de aplicativos.

Possivelmente, se você tiver algum tipo de object typescript em seu database.

Digamos que em uma tabela, T1, você tem as colunas C1, C2, C3 … com uma relação de um para um. Tudo bem, está em forma normalizada. Agora digamos que em uma tabela T2, você tem as colunas C1, C2, C3, … (os nomes podem diferir, mas dizem que os tipos e a function são os mesmos) com uma relação de um para um também. Está tudo bem para o T2 pelas mesmas razões que com o T1.

Neste caso, no entanto, vejo um ajuste para uma tabela separada T3, segurando C1, C2, C3 … e uma relação de um para um de T1 para T3 e de T2 para T3. Eu ainda vejo mais um ajuste se existe outra tabela, com a qual já existe um para vários C1, C2, C3 … digamos da tabela A para múltiplas linhas na tabela B. Então, ao invés de T3, você usa B, e tem uma relação um para um de T1 para B, a mesma para de T2 para B, e ainda a mesma para múltiplas relações de A para B.

Acredito que a normalização não concorda com isso, e isso pode ser uma ideia fora dela: identificar tipos de object e mover objects de um mesmo tipo para seu próprio conjunto de armazenamento, usando uma relação de um para um de algumas tabelas e um para múltiplos relação de algumas outras tabelas.

Você pode criar uma tabela de relacionamento de um para um se houver algum benefício de desempenho significativo. Você pode colocar os campos raramente usados ​​em uma tabela separada.

É desnecessário ótimo para fins de segurança, mas há maneiras melhores de executar verificações de segurança. Imagine, você cria uma chave que só pode abrir uma porta. Se a chave puder abrir qualquer outra porta, você deverá tocar o alarme. Em essência, você pode ter “CitizenTable” e “VotingTable”. Cidadão Um voto para o Candidato Um que é armazenado na Tabela de Votos. Se um cidadão aparecer na mesa de votação novamente, então o seu deve ser um alarme. Seja conselho, este é um relacionamento de um para um, porque não nos referimos ao campo do candidato, estamos nos referindo à mesa de votação e à tabela de cidadãos.

Exemplo:

Citizen Table id = 1, citizen_name = "EvryBod" id = 2, citizen_name = "Lesly" id = 3, citizen_name = "Wasserman" Candidate Table id = 1, citizen_id = 1, candidate_name = "Bern Nie" id = 2, citizen_id = 2, candidate_name = "Bern Nie" id = 3, citizen_id = 3, candidate_name = "Hill Arry" 

Então, se vemos a tabela de votação como assim:

  Voting Table id = 1, citizen_id = 1, candidate_name = "Bern Nie" id = 2, citizen_id = 2, candidate_name = "Bern Nie" id = 3, citizen_id = 3, candidate_name = "Hill Arry" id = 4, citizen_id = 3, candidate_name = "Hill Arry" id = 5, citizen_id = 3, candidate_name = "Hill Arry" 

Poderíamos dizer que o cidadão número 3 é uma calça mentirosa que enganou Bern Nie. Apenas um exemplo.

Em qualquer lugar, duas entidades totalmente independentes compartilham um relacionamento um-para-um. Deve haver muitos exemplos:

pessoa <-> dentista (é 1: N, então está errado!)

pessoa <-> médico (é 1: N, então também está errado!)

pessoa <-> cônjuge (é 1: 0 | 1, então é mais errado!)

EDIT: Sim, esses foram exemplos muito ruins, especialmente se eu estava sempre procurando um 1: 1, não um 0 ou 1 em ambos os lados. Eu acho que meu cérebro estava triggersndo mal 🙂

Então, vou tentar de novo. Acontece, depois de pensar um pouco, que a única maneira pela qual você pode ter duas entidades separadas que devem (tanto quanto o software fica) estar juntas o tempo todo é que elas existam juntas em uma categorização maior. Então, se e somente se você cair em uma decomposição mais baixa, as coisas são e devem ser separadas, mas no nível mais alto elas não podem viver uma sem a outra. Contexto, então é a chave.

Para um database médico, você pode armazenar informações diferentes sobre regiões específicas do corpo, mantendo-as como uma entidade separada. Nesse caso, um paciente tem apenas uma cabeça e precisa ter, ou não é um paciente. (Eles também têm um coração e vários outros órgãos únicos necessários). Se você estiver interessado em rastrear cirurgias, por exemplo, cada região deve ser uma entidade separada única.

Em um sistema de produção / estoque, se você estiver rastreando a assembly de veículos, certamente desejará observar o progresso do motor de maneira diferente do corpo do carro, ainda que haja uma relação de um para um. Um cuidado deve ter um motor e apenas um (ou não seria mais um ‘carro’). Um motor pertence a apenas um carro.

Em cada caso, você poderia produzir as entidades separadas como um grande registro, mas dado o nível de decomposição, isso seria errado. Eles são, nesses contextos específicos, entidades verdadeiramente independentes, embora possam não aparecer em um nível mais alto.

Paulo.