AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 5222
Accepted
Thomas Stringer
Thomas Stringer
Asked: 2011-08-31 13:11:39 +0800 CST2011-08-31 13:11:39 +0800 CST 2011-08-31 13:11:39 +0800 CST

Por que não devemos permitir NULLs?

  • 772

Lembro-me de ler este artigo sobre design de banco de dados e também me lembro de dizer que você deve ter propriedades de campo NOT NULL. Eu não me lembro porque este foi o caso embora.

Tudo o que consigo pensar é que, como desenvolvedor de aplicativos, você não precisaria testar NULL e um possível valor de dados inexistente (por exemplo, uma string vazia para strings).

Mas o que você faz no caso de datas, datetime e time (SQL Server 2008)? Você teria que usar alguma data histórica ou de fundo.

Alguma idéia sobre isso?

database-design null
  • 8 8 respostas
  • 66384 Views

8 respostas

  • Voted
  1. Best Answer
    Aaron Bertrand
    2011-08-31T15:01:02+08:002011-08-31T15:01:02+08:00
    Bloqueado . Os comentários sobre esta resposta foram desativados, mas ainda está aceitando outras interações. Saiba mais .

    Acho que a pergunta está mal formulada, pois o texto implica que você já decidiu que NULLs são ruins. Talvez você quis dizer "Devemos permitir NULLs?"

    De qualquer forma, aqui está minha opinião: acho que NULLs são uma coisa boa. Quando você começa a evitar NULLs apenas porque "NULLs são ruins" ou "NULLs são difíceis", você começa a criar dados. Por exemplo, e se você não souber minha data de nascimento? O que você vai colocar na coluna até saber? Se você for como um monte de gente anti-NULL, você vai digitar 1900-01-01. Agora vou ser colocado na ala geriátrica e provavelmente receberei uma ligação da minha estação de notícias local parabenizando-me por minha longa vida, perguntando-me meus segredos para viver uma vida tão longa etc.

    Se uma linha pode ser inserida onde é possível que você não saiba o valor de uma coluna, acho que NULL faz muito mais sentido do que escolher algum valor de token arbitrário para representar o fato de que é desconhecido - um valor que outros irão precisa saber, fazer engenharia reversa ou perguntar por aí para descobrir o que isso significa.

    No entanto, há um equilíbrio - nem todas as colunas em seu modelo de dados devem ser anuláveis. Geralmente, há campos opcionais em um formulário ou informações que, de outra forma, não são coletadas no momento em que a linha é criada. Mas isso não significa que você pode adiar o preenchimento de todos os dados. :-)

    Além disso, a capacidade de usar NULL pode ser limitada por requisitos cruciais na vida real. Na área médica, por exemplo, pode ser uma questão de vida ou morte saber por que um valor é desconhecido. A frequência cardíaca é NULA porque não havia pulso ou porque ainda não a medimos? Nesse caso, podemos colocar NULL na coluna de frequência cardíaca e ter notas ou uma coluna diferente com um motivo NULL-becau?

    Não tenha medo de NULLs, mas esteja disposto a aprender ou ditar quando e onde eles devem ser usados, e quando e onde não devem.

    • 261
  2. bignose
    2011-09-22T19:08:00+08:002011-09-22T19:08:00+08:00

    As razões estabelecidas são:

    • NULL não é um valor e, portanto, não possui tipo de dados intrínseco. Nulos precisam de tratamento especial em todos os lugares quando o código que depende de tipos reais também pode receber o NULL não tipado.

    • NULL quebra a lógica de dois valores (familiar True ou False) e requer uma lógica de três valores. Isso é muito mais complexo até mesmo para implementar corretamente e certamente é mal compreendido pela maioria dos DBAs e quase todos os não-DBAs. Como consequência, ele convida positivamente muitos bugs sutis no aplicativo.

    • O significado semântico de qualquer NULL específico é deixado para o aplicativo , ao contrário dos valores reais.

      Semânticas como “não aplicável” e “desconhecido” e “sentinela” são comuns, e existem outras também. Eles são frequentemente usados ​​simultaneamente dentro de um mesmo banco de dados, mesmo dentro da mesma relação; e são, obviamente, significados inexplícitos e indistinguíveis e incompatíveis .

    • Eles não são necessários para bancos de dados relacionais , conforme argumentado em “Como lidar com informações ausentes sem nulos” . A normalização adicional é um primeiro passo óbvio para tentar livrar uma tabela de NULLs.

    Isso não significa que NULL nunca deve ser permitido. Ele argumenta que há muitas boas razões para não permitir NULL sempre que possível.

    Significativamente, ele argumenta para tentar muito – por meio de um melhor design de esquema, melhores mecanismos de banco de dados e linguagens de banco de dados ainda melhores – para tornar viável evitar NULL com mais frequência.

    Fabian Pascal responde a uma série de argumentos, em “Nulls Nullified” .

    • 72
  3. Mark Storey-Smith
    2011-08-31T13:32:57+08:002011-08-31T13:32:57+08:00

    Eu discordo, nulos são um elemento essencial do design de banco de dados. A alternativa, como você aludiu também, seria uma proliferação de valores conhecidos para representar o que falta ou o desconhecido. O problema está no fato de null ser tão amplamente incompreendido e, como resultado, ser usado de forma inadequada.

    IIRC, Codd sugeriu que a implementação atual de null (significando não presente/ausente) poderia ser melhorada com dois marcadores nulos em vez de um, "não presente, mas aplicável" e "não presente e não aplicável". Não consigo imaginar como os designs relacionais seriam melhorados por isso pessoalmente.

    • 35
  4. Nicholas Aguirre
    2014-12-10T13:10:52+08:002014-12-10T13:10:52+08:00

    Deixe-me começar dizendo que não sou um DBA, sou um desenvolvedor de coração e mantenho e atualizo nossos bancos de dados com base em nossas necessidades. Dito isto, eu tinha a mesma pergunta por alguns motivos.

    1. Valores nulos tornam o desenvolvimento mais difícil e propenso a erros.
    2. Valores nulos tornam as consultas, procedimentos armazenados e visualizações mais complexas e propensas a erros.
    3. Valores nulos ocupam espaço (? bytes com base no comprimento fixo da coluna ou 2 bytes para o comprimento variável da coluna).
    4. Valores nulos podem e muitas vezes afetam a indexação e a matemática.

    Passo muito tempo vasculhando as cargas de respostas, comentários, artigos e conselhos por toda a internet. Escusado será dizer que a maioria das informações era quase a mesma da resposta de @AaronBertrand. Por isso senti a necessidade de responder a esta pergunta.

    Em primeiro lugar, quero definir algo direto para todos os futuros leitores... Valores NULL representam dados desconhecidos NÃO dados não utilizados. Se você tiver uma tabela de funcionários que tenha um campo de data de rescisão. Um valor nulo na data de término é porque é um campo obrigatório futuro que é atualmente desconhecido. Todo funcionário, seja ele ativo ou demitido, em algum momento terá uma data adicionada a esse campo. Essa é, na minha opinião, a única razão para um campo anulável.

    Dito isto, a mesma tabela de funcionários provavelmente conteria algum tipo de dados de autenticação. É comum em um ambiente corporativo que os funcionários sejam listados no banco de dados para RH e contabilidade, mas nem sempre tenham ou precisem de detalhes de autenticação. A maioria das respostas levaria você a acreditar que não há problema em anular esses campos ou, em alguns casos, criar uma conta para eles, mas nunca enviar as credenciais. O primeiro fará com que sua equipe de desenvolvimento escreva código para verificar se há NULLs e lidar com eles de acordo e o último representa um enorme risco de segurança! Contas que ainda não são usadas no sistema apenas aumentam o número de pontos de acesso possíveis para um hacker, além de ocuparem um valioso espaço de banco de dados para algo que nunca é usado.

    Dadas as informações acima, a melhor maneira de lidar com dados anuláveis ​​que serão usados ​​é permitir valores anuláveis. É triste, mas é verdade e seus desenvolvedores vão odiá-lo por isso. O segundo tipo de dados anuláveis ​​deve ser colocado em uma tabela relacionada (IE: Conta, Credenciais, etc) e ter um relacionamento Um para Um. Isso permite que um usuário exista sem credenciais, a menos que sejam necessárias. Isso elimina o risco extra de segurança, o valioso espaço do banco de dados e fornece um banco de dados muito mais limpo.

    Abaixo está uma estrutura de tabela muito simplista que mostra a coluna anulável necessária e um relacionamento um para um.

    Relacionamento anulável e um para um desconhecido

    Eu sei que estou um pouco atrasado para a festa desde que essa pergunta foi feita anos atrás, mas espero que isso ajude a lançar alguma luz sobre esse problema e a melhor forma de lidar com isso.

    • 16
  5. Thomas Kejser
    2016-04-05T06:31:40+08:002016-04-05T06:31:40+08:00

    Além de todos os problemas com desenvolvedores NULL confusos, NULLs têm outra desvantagem muito séria: Desempenho

    Colunas NULL'able são um desastre do ponto de vista de desempenho. Considere a aritmética de inteiros como um exemplo. Em um mundo são sem NULL, é "fácil" vetorizar aritmética inteira no código do mecanismo de banco de dados usando instruções SIMD para realizar praticamente qualquer cálculo em velocidades mais rápidas que 1 linha por ciclo de CPU. No entanto, no momento em que você introduz NULL, você precisa lidar com todos os casos especiais que NULL cria. Conjuntos de instruções de CPU modernos (leia-se: x86/x64/ARM e lógica de GPU também) simplesmente não estão equipados para fazer isso com eficiência.

    Considere a divisão como um exemplo. Em um nível muito alto, esta é a lógica que você precisa com um inteiro não nulo:

    if (b == 0)
      do something when dividing by error
    else
      return a / b
    

    Com NULL, isso se torna um pouco mais complicado. Junto com bvocê precisará de um indicador se bfor nulo e da mesma forma para a. O cheque agora se torna:

    if (b_null_bit == NULL)
       return NULL
    else if (b == 0) 
       do something when dividing by error
    else if (a_null_bit == NULL)
       return NULL
    else 
       return a / b
    

    A aritmética NULL é significativamente mais lenta para ser executada em uma CPU moderna do que a aritmética não nula (por um fator de cerca de 2-3x).

    Fica pior quando você introduz o SIMD. Com SIMD, uma CPU Intel moderna pode realizar 4 divisões inteiras de 32 bits em uma única instrução, assim:

    x_vector = a_vector / b_vector
    if (fetestexception(FE_DIVBYZERO))
       do something when dividing by zero
    return x_vector;
    

    Agora, existem maneiras de lidar com NULL na terra SIMD também, mas isso requer o uso de mais vetores e registradores de CPU e fazer algumas máscaras de bits inteligentes. Mesmo com bons truques, a penalidade de desempenho da aritmética inteira NULL se arrasta para o intervalo de 5 a 10 vezes mais lento para expressões relativamente simples.

    Algo como o acima vale para agregados e, até certo ponto, para junções também.

    Em outras palavras: a existência de NULL no SQL é uma incompatibilidade de impedância entre a teoria do banco de dados e o projeto real dos computadores modernos. Há uma boa razão para NULL confundir os desenvolvedores - porque um inteiro não pode ser NULL na maioria das linguagens de programação sãs - não é assim que os computadores funcionam.

    • 14
  6. Derek Downey
    2011-08-31T13:34:44+08:002011-08-31T13:34:44+08:00

    O artigo da Wikipedia sobre SQL Null tem algumas observações interessantes sobre o valor NULL e, como uma resposta independente de banco de dados, desde que você esteja ciente dos efeitos potenciais de ter valores NULL para seu RDBMS específico, eles são aceitáveis ​​em seu design. Se não fossem, você não seria capaz de especificar colunas como anuláveis.

    Apenas esteja ciente de como seu RDBMS lida com eles em operações SELECT, como matemática, e também em índices.

    • 11
  7. Chris Travers
    2013-02-24T06:08:15+08:002013-02-24T06:08:15+08:00

    Perguntas interessantes.

    Tudo o que consigo pensar é que, como desenvolvedor de aplicativos, você não precisaria testar NULL e um possível valor de dados inexistente (por exemplo, uma string vazia para strings).

    É mais complicado do que isso. Null tem vários significados distintos e uma razão realmente importante para não permitir nulos em muitas colunas é que quando a coluna é nula isso significa uma e apenas uma coisa (ou seja, que não apareceu em uma junção externa). Além disso, permite definir padrões mínimos de entrada de dados, o que é realmente útil.

    Mas o que você faz no caso de datas, datetime e time (SQL Server 2008)? Você teria que usar alguma data histórica ou de fundo.

    Isso ilustra um problema com nulos imediatamente, ou seja, que um valor armazenado em uma tabela pode significar "este valor não se aplica" ou "não sabemos". Com strings, uma string vazia pode servir como "isto não se aplica", mas com datas e horas, não existe tal convenção porque não há valor válido que convencionalmente signifique isso. Normalmente, você ficará preso usando NULLs.

    Existem maneiras de contornar isso (adicionando mais relações e unindo), mas essas apresentam exatamente os mesmos problemas de clareza semântica que ter NULLs no banco de dados. Para esses bancos de dados eu não me preocuparia com isso. Não há nada que você possa fazer sobre isso realmente.

    EDIT: Uma área onde NULLs são indispensáveis ​​é em chaves estrangeiras. Aqui eles normalmente têm apenas um significado, idêntico ao nulo no significado de junção externa. Esta é uma exceção ao problema, é claro.

    • 11
  8. Matthew Sontum
    2017-02-25T03:40:09+08:002017-02-25T03:40:09+08:00

    Uau, a resposta correta "Não permita NULLs quando você não precisa porque eles degradam o desempenho" é de alguma forma a última resposta avaliada. Vou upvote-lo e elaborar. Quando um RDBMS permite NULLs para uma coluna não esparsa, essa coluna é adicionada a um bitmap que rastreia se o valor é NULL para cada linha individual. Portanto, ao adicionar a capacidade NULL a uma coluna em uma tabela em que todas as colunas não permitem NULLs, você está aumentando o espaço de armazenamento necessário para salvar a tabela. Além disso, você está exigindo que o RDBMS leia e grave no bitmap, degradando o desempenho em todas as operações.

    Além disso, em vários casos, permitir NULLs quebrará o 3NF. Embora eu não seja um defensor da 3NF como muitos dos meus colegas, considere o seguinte cenário:

    Na tabela Person há uma coluna, chamada DateOfDeath, que é anulável. Se uma pessoa morreu, ele será preenchido com sua Data de Morte, caso contrário, será deixado NULL. Há também uma coluna de bits não anulável chamada IsAlive. Esta coluna é definida como 1 se a pessoa estiver viva e 0 se a pessoa estiver morta. A grande maioria dos procedimentos armazenados usa a coluna IsAlive, eles se importam apenas se uma pessoa está viva, não seu DateOfDeath.

    No entanto, a coluna IsAlive interrompe a normalização do banco de dados, porque é completamente derivável de DateOfDeath. Mas como o IsAlive está conectado à maioria dos SPs, a solução direta é tornar DateOfDeath não anulável e atribuir um valor padrão à coluna caso a pessoa ainda esteja viva. Os poucos SPs que usam DateOfDeath podem ser reescritos para verificar a coluna IsAlive e somente honrar a DateOfDeath se a pessoa não estiver viva. Novamente, como a maioria dos SPs se preocupa apenas com IsAlive (um pouco) e não com DateOfDeath (uma data), usar esse padrão acelera o acesso consideravelmente.

    Um script T-SQL útil para localizar colunas anuláveis ​​sem NULLs em todos os esquemas é:

    select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
        AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
        from sys.columns c
        inner join sys.tables t ON c.object_id = t.object_id
        inner join sys.schemas s ON s.schema_id = t.schema_id
        where c.is_nullable = 1 AND c.is_computed = 0
        order by s.name, t.name, c.name;
    

    Se você executar isso em uma cópia do seu banco de dados de produção, poderá encontrar as colunas que os desenvolvedores marcaram como permitindo NULLs que não possuem NULLs na prática. A grande maioria deles pode ser marcada como NOT NULL, aumentando assim o desempenho e reduzindo o espaço de armazenamento.

    Pode não ser possível eliminar todos os NULLs em todas as tabelas e ainda ter um design limpo, mas há uma vantagem considerável em eliminar o maior número possível de NULLs. O otimizador trabalha muito mais rápido com essas informações e, se você puder eliminar todos os NULLs em uma tabela, poderá recuperar uma quantidade considerável de espaço de armazenamento.

    Eu sei que desempenho não é algo que os DBAs pensam muito, mas você só pode usar uma quantidade limitada de memória e poder de processador em uma solução, em algum momento você terá que começar a pensar em design lógico e físico .

    Observe também que isso é apenas para RDBMSes verdadeiros e estou baseando a parte técnica de minhas respostas no SQL Server. O T-SQL listado para localizar colunas anuláveis ​​sem nulos também é do SQL Server.

    • -10

relate perguntas

  • É melhor armazenar os valores calculados ou recalculá-los a pedido? [duplicado]

  • Armazenar vs calcular valores agregados

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

  • NULL ou NOT NULL por padrão?

  • Quando usar NULL e quando usar uma string vazia?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como você mostra o SQL em execução em um banco de dados Oracle?

    • 2 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Posso ver Consultas Históricas executadas em um banco de dados SQL Server?

    • 6 respostas
  • Marko Smith

    Como uso currval() no PostgreSQL para obter o último id inserido?

    • 10 respostas
  • Marko Smith

    Como executar o psql no Mac OS X?

    • 11 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Marko Smith

    Passando parâmetros de array para um procedimento armazenado

    • 12 respostas
  • Martin Hope
    Manuel Leduc Restrição exclusiva de várias colunas do PostgreSQL e valores NULL 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler Quando uma chave primária deve ser declarada sem cluster? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - Qual é melhor como chave primária? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick Como posso otimizar um mysqldump de um banco de dados grande? 2011-01-04 13:13:48 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve