O que os bancos de dados relacionais ganham definindo um tipo de dados predefinido para cada coluna?


44

Estou trabalhando com um banco de dados SQL no momento e isso sempre me deixou curioso, mas as pesquisas no Google não aparecem muito: por que os tipos de dados estritos?

Entendo por que você teria alguns tipos de dados diferentes, por exemplo, como é importante a diferenciação entre dados binários e dados de texto sem formatação . Em vez de armazenar os 1s e 0s dos dados binários como texto sem formatação, agora entendo que é mais eficiente armazenar os dados binários como seu próprio formato.

Mas o que não entendo é qual é o benefício de ter tantos tipos diferentes de dados:

  • Porque mediumtext, longtexte text?
  • Porque decimal, floate int?
  • etc.

Qual é o benefício de informar ao banco de dados "Só haverá 256 bytes de dados de texto sem formatação nas entradas desta coluna". ou "Esta coluna pode ter entradas de texto de até 16.777.215 bytes"?

É um benefício de desempenho? Em caso afirmativo, por que saber o tamanho da entrada antecipadamente ajuda no desempenho? Ou melhor, é algo completamente diferente?


2
Achei que essa pergunta já deveria existir aqui, mas pesquisei no site e não encontrei nada útil.
Joao doe


6
Se você não tem distintas decimal, floate inttipos, o que você esperaria 1 / 3que fazer? Que tal 1.0 / 3.0? Você poderia ter certeza de que, ao se dividir columnA, columnBobterá os resultados esperados?
Andrew diz Reinstate Monica

2
@johndoe Acho que nunca seria necessário, mas poderia ser muito conveniente. Digamos que você queira impor uma restrição de que o estoque de uma loja não pode ser inferior a 5% de suas vendas mensais esperadas. Ou você deseja garantir que o orçamento total de cada divisão não ultrapasse 20% do orçamento total. Também pode aparecer em colunas computadas que você deseja calcular da mesma maneira em vários aplicativos usando o mesmo banco de dados.
Andrew diz Reinstate Monica

2
Vale ressaltar que o SQLite não define um tipo predefinido por coluna : "SQLite é" sem tipo de letra ". Isso significa que você pode armazenar qualquer tipo de dados que desejar em qualquer coluna de qualquer tabela, independentemente do tipo de dados declarado dessa coluna. "
Prime

Respostas:


50

SQL é uma linguagem de tipo estaticamente . Isso significa que você precisa saber que tipo de variável (ou campo, nesse caso) é antes de poder usá-la. É o oposto de linguagens de tipo dinâmico, onde esse não é necessariamente o caso.

Em sua essência, o SQL foi projetado para definir dados ( DDL ) e acessar dados ( DML ) em um mecanismo de banco de dados relacional . A digitação estática apresenta vários benefícios sobre a digitação dinâmica para esse tipo de sistema.

  • Os índices , usados ​​para acessar rapidamente registros específicos, funcionam muito bem quando o tamanho é fixo. Considere uma consulta que utilize um índice, possivelmente com vários campos: se os tipos e tamanhos de dados forem conhecidos antecipadamente, posso comparar rapidamente meu predicado (cláusula WHERE ou critério JOIN) com os valores no índice e encontrar os registros desejados mais rapidamente .

  • Considere dois valores inteiros . Em um sistema de tipo dinâmico, eles podem ter tamanho variável (pense em Java BigInteger, ou inteiros de precisão arbitrária internos do Python). Se eu quiser comparar os números inteiros, primeiro preciso saber o tamanho dos bits. Esse é um aspecto da comparação de números inteiros, que é amplamente oculto pelas linguagens modernas, mas é muito real no nível da CPU. Se os tamanhos forem fixos e conhecidos com antecedência, uma etapa inteira será removida do processo. Novamente, os bancos de dados devem ser capazes de processar zilhões de transações o mais rápido possível. A velocidade é rei.

  • O SQL foi projetado nos anos 70. Nos primeiros dias da microcomputação, a memória era um prêmio. A limitação de dados ajudou a manter os requisitos de armazenamento sob controle. Se um número inteiro nunca ultrapassa um byte, por que alocar mais armazenamento para ele? Isso é espaço desperdiçado na era da memória limitada. Mesmo nos tempos modernos, esses bytes extras desperdiçados podem adicionar e prejudicar o desempenho do cache de uma CPU. Lembre-se, esses são mecanismos de banco de dados que podem atender centenas de transações por segundo, não apenas seu pequeno ambiente de desenvolvimento.

  • Na linha de armazenamento limitado, é útil poder ajustar um único registro em uma única página na memória. Depois de percorrer uma página, há mais falhas de página e mais acesso à memória lento. Os mecanismos mais recentes têm otimizações para tornar isso menos um problema, mas ele ainda está lá. Ao dimensionar os dados adequadamente, você pode atenuar esse risco.

  • Nos tempos modernos, o SQL é usado para conectar-se a outros idiomas via ORM ou ODBC ou alguma outra camada. Algumas dessas linguagens têm regras sobre a exigência de tipos estáticos fortes. É melhor estar em conformidade com os requisitos mais rigorosos, pois as linguagens de tipo dinâmico podem lidar com tipos estáticos mais facilmente do que o contrário.

  • O SQL suporta digitação estática porque os mecanismos de banco de dados precisam dela para desempenho, como mostrado acima.

É interessante notar que existem implementações de SQL que não são fortemente tipadas. O SQLite é provavelmente o exemplo mais popular desse mecanismo de banco de dados relacional. Por outro lado, ele foi projetado para uso de thread único em um único sistema, de modo que as preocupações de desempenho podem não ser tão pronunciadas quanto em, por exemplo, um banco de dados Oracle corporativo que atende milhões de solicitações por minuto.


SQLite tem tipos de dados que fazem distinção entre os dados numéricos e de texto, mas só tem 5 "classes" de armazenamento de dados: sqlite.org/datatype3.html
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner Eu sei, mas ainda não é tão rigoroso quanto os mecanismos como SQL Server, Oracle ou PostgreSQL.

O SQL não é apenas digitado estaticamente - devido à presença de restrições de verificação, ele suporta efetivamente tipos de refinamento.
Gardenhead 26/05

4
Embora implícito no primeiro marcador Indexes, mais basicamente afirmado: ter um tipo de dados permite que o mecanismo de banco de dados compreenda os dados e faça comparações (números maiores / menores, datas anteriores / posteriores, antes / depois no alfabeto), e, portanto, permite classificar e consultar .
Basil Bourque

Portanto, se os tamanhos são importantes ... e o sql precisa saber de antemão ... qual é o tamanho exato de uma transação "Zillion"?
WernerCD

24

Primeiro: o texto simples é binário (nem mesmo os caracteres UTF8 ou ASCII "0" e "1" são os bits ativados / desativados)

Dito isto, alguns dos motivos são:

  • Restrições de negócios / design: permitir que o número 7626355112 na coluna HEIGHT da tabela PERSON estivesse errado. Permitir "Howya" na coluna DATA de uma FATURA estaria errado.
  • Código menos propenso a erros: você não precisa escrever um código para garantir que os dados recuperados de uma coluna de data sejam realmente uma data. Se os tipos de coluna fossem dinâmicos, você teria que fazer muitas verificações de tipo ao lê-las.
  • Eficiência de computação: se uma coluna é do tipo INTEGER e você a soma (), o RDBMS não precisa aplicar aritmética de ponto flutuante.
  • Eficiência de armazenamento: declarar que uma coluna é VARCHAR (10) permite que o RDBMS aloque espaço com mais precisão.
  • Integridade referencial e unicidade: as PK (ou FKs) de uma tabela não devem permitir flutuações, pois a igualdade de ponto flutuante é complicada; portanto, você deve declará-las em um tipo não flutuante, como caracteres ou número inteiro.
  • Existem RDBMSs com tipos de colunas dinâmicos (não estritos) (SQLite) . Ele usa o conceito de "afinidade de tipo" e ainda permite inserir praticamente qualquer coisa em qualquer coluna sem reclamar. Existem trade-offs que não serão discutidos aqui. Veja esta pergunta .

8

É assim que o código subjacente no qual o banco de dados está gravado pode alocar e usar registros de tamanho fixo, se souber que um campo específico pode conter de 0 a 256 caracteres de texto, ele poderá alocar um bloco de 256 bytes para armazená-lo.

Isso torna as coisas muito mais rápidas, por exemplo, você não precisa alocar armazenamento adicional à medida que o usuário digita, pois um determinado campo sempre inicia x bytes no registro, uma pesquisa ou seleção nesse campo sabe sempre verificar x bytes em cada registro, etc.


Se todas as respostas poderiam ser este conciso e direto ao ponto ...
Darren Ringer

6

Quando as colunas de um banco de dados recebem tipos definidos, os tipos geralmente são definidos como tendo um certo tamanho em bits. Como um resultado:

1) quando o mecanismo de banco de dados está percorrendo as linhas em uma tabela, ele não precisa fazer nenhuma análise sofisticada para determinar onde cada registro termina, basta saber que cada linha consiste em, digamos, 32 bytes e, portanto, para obter o No próximo registro, é suficiente adicionar 32 bytes ao local atual dos registros.

2) ao procurar um campo dentro de uma linha, é possível conhecer um deslocamento exato para esse campo novamente sem analisar nada, para que as pesquisas de coluna sejam uma operação aritmética simples e não uma operação de processamento de dados potencialmente dispendiosa.


Os campos de comprimento fixo podem tornar o processamento mais eficiente devido a comprimentos consistentes de registros e deslocamentos de campo, mas os campos de comprimento variável podem anular esses benefícios porque o comprimento e o deslocamento dos campos podem variar. Da mesma forma, a compactação no nível do registro resultará em registros de tamanho variável, portanto a localização de um determinado registro não pode ser simplesmente calculada.
Zenilogix 28/05

Isso é verdade e, por um longo tempo, foi um conselho comum evitar campos de comprimento variável exatamente por esse motivo. Não sei como os grandes jogadores fazem isso, mas parece que você pode recuperar alguns dos benefícios do comprimento fixo, fazendo com que o mecanismo armazene campos de largura variável em uma tabela ou bloco de memória não visível ao usuário e tenha o A representação de tabelas primárias desses campos é um 'ponteiro' (largura fixa) para ele. Considerando que você deve fazer varreduras completas regularmente de campos de comprimento variável, em primeiro lugar, o impacto no desempenho do indireto pode valer a pena manter larguras fixas.
UserNotFound

3

Você perguntou por que os DBMSs têm tipos de dados estáticos.

  1. Velocidade de pesquisa. O objetivo de um DBMS é armazenar muito mais dados do que você poderia carregar em um programa. Pense em "todos os recibos de cartão de crédito gerados no mundo nos últimos dez anos". Para pesquisar esses dados com eficiência, tipos de dados de comprimento fixo são úteis. Isso é especialmente verdadeiro para dados estruturados, como carimbos de data e números de conta. Se você sabe com o que está lidando com antecedência, é mais fácil carregar em índices eficientes.

  2. Integridade e restrições. É mais fácil manter os dados limpos se houver tipos de dados fixos.

  3. História. Os RDBMSs começaram quando os computadores tinham apenas alguns megabytes de RAM e o armazenamento em escala de terabytes era muito caro. Salvar uma dúzia de bytes em cada linha de uma tabela pode economizar milhares de dólares e horas nessas circunstâncias.

  4. A maldição da base de clientes. Hoje, os RDBMSs são pacotes de software muito complexos, altamente otimizados e estão em uso há décadas acumulando dados. Eles são maduros. Eles trabalham. Um travamento do RDBMS que resulta em perda de dados em larga escala é extremamente raro atualmente. Mudar para algo com um sistema de digitação de dados mais flexível não vale o custo ou o risco para a maioria das organizações.

Analogia: pode ser óbvio que os sistemas de metrô urbanos funcionariam melhor (mais silenciosos, mais rápidos, mais eficientes em termos de energia) em uma bitola mais estreita. Mas como você vai mudar todos os trilhos do sistema de metrô de Nova York para obter essas melhorias? Você não é, então você otimiza o que tem.


3

Em geral, quanto mais detalhes você informar ao banco de dados sobre o que está armazenando, mais ele poderá tentar otimizar várias métricas de desempenho relacionadas a esses dados, como quanto espaço alocar no disco ou quanta memória alocar ao recuperá-lo. .

Por que texto médio, texto longo e texto?

Não tenho certeza de qual banco de dados você está usando, então vou ter que adivinhar: eu acho que dois desses tipos de dados têm limites superiores, um deles não. O uso de tipos de dados para texto com limites superiores informa ao banco de dados quanto espaço de armazenamento será necessário para cada registro. Também é possível que alguns bancos de dados possuam maneiras diferentes de armazenar texto grande (possivelmente ilimitado) versus texto pequeno de tamanho fixo (isso pode variar de acordo com o banco de dados, consulte o manual para ver o seu).

Por que decimal, float e int?

Diferentes níveis de precisão requerem diferentes quantidades de armazenamento, e nem todo uso exige os mais altos graus de precisão. Por exemplo, consulte aqui: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

A Oracle possui vários tipos numéricos diferentes, com diferentes requisitos de armazenamento e recursos diferentes em termos de nível de precisão e tamanho do número que pode ser representado.


2

Até certo ponto, é histórico.

Era uma vez, dados tabulares eram armazenados em arquivos compostos por registros de comprimento fixo, por sua vez compostos por campos predefinidos, de modo que um determinado campo era sempre do mesmo tipo e no mesmo local de todos os registros. Isso tornou o processamento eficiente e limitou a complexidade da codificação.

Adicione alguns índices a esse arquivo e você terá o início de um banco de dados relacional.

À medida que os bancos de dados relacionais evoluíram, eles começaram a introduzir mais tipos de dados e opções de armazenamento, incluindo texto de tamanho variável ou campos binários. Porém, isso introduziu registros de tamanho variável e interrompeu a capacidade de localizar consistentemente registros via cálculo ou campos por meio de um deslocamento fixo. Não importa, as máquinas são muito mais poderosas hoje do que eram naquela época.

Às vezes, é útil definir um tamanho específico para um campo para ajudar a impor um pouco da lógica comercial - digamos 10 dígitos para um número de telefone norte-americano. Na maioria das vezes, é apenas um pouco do legado da computação.


1

Se um banco de dados usar registros de tamanho fixo, qualquer registro no banco de dados continuará a se ajustar, no mesmo local, mesmo que seu conteúdo seja alterado. Por outro lado, se um banco de dados tenta armazenar registros usando exatamente a quantidade de armazenamento necessária para seus campos, alterar o nome de Emma Smith para Emma Johnson pode fazer com que seu registro seja muito grande para caber no local atual. Se o registro for movido para algum lugar com espaço suficiente, qualquer índice que rastreie sua localização precisará ser atualizado para refletir o novo local.

Existem várias maneiras de reduzir o custo associado a essas atualizações. Por exemplo, se o sistema mantiver uma lista de números de registros e locais de dados, essa lista será a única coisa que precisaria ser atualizada se um registro se mover. Infelizmente, essas abordagens ainda têm um custo significativo (por exemplo, manter um mapeamento entre números e locais de registros exigiria que a recuperação de registros exigisse uma etapa extra para recuperar os dados associados a um determinado número de registro). O uso de registros de tamanho fixo pode parecer ineficiente, mas torna as coisas muito mais simples.


1

Para muito do que você faz como desenvolvedor da Web, não há necessidade de entender o que está acontecendo "oculto". Há momentos, no entanto, quando isso ajuda.

Qual é o benefício de informar ao banco de dados "Só haverá 256 bytes de dados de texto sem formatação nas entradas desta coluna". ou "Esta coluna pode ter entradas de texto de até 16.777.215 bytes"?

Como você suspeita, o motivo é a eficiência. As abstrações vazam . Uma consulta como SELECT author FROM bookspode ser executada rapidamente quando o tamanho de todos os campos da tabela é conhecido.

Como Joel diz,

Como um banco de dados relacional é implementado SELECT author FROM books? Em um banco de dados relacional, todas as linhas de uma tabela (por exemplo, a tabela de livros) têm exatamente o mesmo comprimento em bytes e todos os campos estão sempre em um deslocamento fixo desde o início da linha. Portanto, por exemplo, se cada registro na tabela de livros tiver 100 bytes e o campo do autor estiver no deslocamento 23, haverá autores armazenados nos bytes 23, 123, 223, 323 etc. Qual é o código para o qual mover o próximo registro no resultado desta consulta? Basicamente, é isso:

pointer += 100;

Uma instrução de CPU. Faaaaaaaaaast.

Na maioria das vezes, você está trabalhando longe o suficiente dos fundamentos básicos para não precisar se preocupar com isso. Como um desenvolvedor da Web baseado em PHP, você se importa com quantas instruções de CPU seu código usa? Na maioria das vezes, não, na verdade não. Mas, às vezes, é útil saber, por dois motivos: pode explicar as decisões tomadas pelas suas bibliotecas; e às vezes você precisa se preocupar com a velocidade em seu próprio código.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.