Como escolher o tipo numérico correto em SQL — INT, BIGINT, DECIMAL e FLOAT na prática [Guia de design de BD]

Quando você projeta uma tabela no banco de dados, como decide qual tipo numérico atribuir a cada coluna?

“Só usar INT pra inteiros.” “Melhor prevenir do que remediar — coloca BIGINT.” “Tem casa decimal, então FLOAT.” Se essas frases soam familiares, você não está sozinho. Mas esse tipo de decisão no automático pode causar problemas de desempenho, desperdício de armazenamento e até bugs críticos em cálculos financeiros lá na frente.

Pense nisso: trocar INT por BIGINT em uma única coluna de uma tabela com 100 milhões de linhas acrescenta aproximadamente 400 MB de armazenamento. Inclua dois índices e a diferença ultrapassa 1 GB. No outro extremo, usar INT em uma tabela de logs de alto volume que cresce milhões de linhas por dia pode estourar o limite em poucos anos, derrubando toda a aplicação.

E tem o FLOAT. A maioria dos devs sabe que 0.1 + 0.2 resulta em 0.30000000000000004 em vez de 0.3. Mesmo assim, colunas FLOAT continuam aparecendo em tabelas de pagamento em produção, acumulando erros de arredondamento silenciosamente até que os relatórios mensais de receita parem de bater.

Este artigo é um guia completo dos quatro tipos numéricos SQL mais importantes — INT, BIGINT, DECIMAL e FLOAT — cobrindo suas diferenças, trade-offs e regras práticas de decisão que você pode aplicar imediatamente.

💡 Dica

Design de banco de dados é a base de qualquer sistema de software. Para fundamentos de design orientado a objetos, veja o Guia de Princípios SOLID. Para ajuda na escolha de uma linguagem de programação, confira o Guia Comparativo de Linguagens de Programação.

Tipos Numéricos SQL em Resumo

Comece pelo panorama geral. A tabela abaixo resume os principais tipos numéricos. Cada seção seguinte aprofunda os detalhes.

TipoTamanhoFaixa (aprox.)PrecisãoUso Típico
TINYINT1 byte0 – 255 / -128 – 127ExataFlags, códigos de status
SMALLINT2 bytes0 – 65.535ExataContadores pequenos
INT4 bytes~2,1 bilhões / ~4,2 bilhõesExataIDs, quantidades, contadores
BIGINT8 bytes~9,2 quintilhõesExataIDs de log, PKs em larga escala
DECIMAL(M,D)VariávelM dígitos (D casas decimais)ExataDinheiro, alíquotas, taxas
FLOAT4 bytes±3,4 × 10³⁸AproximadaTemperatura, dados de sensores
DOUBLE8 bytes±1,7 × 10³⁰⁸AproximadaCoordenadas GPS, estatística

Os quatro tipos mais importantes no dia a dia são INT, BIGINT, DECIMAL e FLOAT. Domine esses quatro e você resolverá a grande maioria dos designs de banco de dados sem problemas.

Tipos Inteiros (Família INT) — O Ponto de Partida Padrão

Inteiros são o tipo numérico mais rápido, mais eficiente em armazenamento e livre de erros no SQL. Eles vencem em velocidade de cálculo, eficiência de índices e consumo de disco. Se uma coluna não precisa de casas decimais, um tipo inteiro é sempre a escolha certa.

O MySQL oferece cinco tamanhos de inteiro:

TipoTamanhoFaixa SIGNEDFaixa UNSIGNED
TINYINT1 byte-128 a 1270 a 255
SMALLINT2 bytes-32.768 a 32.7670 a 65.535
MEDIUMINT3 bytes-8.388.608 a 8.388.6070 a 16.777.215
INT4 bytes-2.147.483.648 a 2.147.483.6470 a 4.294.967.295
BIGINT8 bytes-9,2 quintilhões a 9,2 quintilhões0 a ~18,4 quintilhões

A regra de ouro: se pode ser representado como inteiro, use um tipo inteiro. Por exemplo, se o seu sistema armazena preços em centavos inteiros (R$), preco_centavos INT funciona perfeitamente. INT suporta até cerca de 2,1 bilhões, o que significa valores de até R$ 21 milhões em centavos — mais que suficiente para a maioria dos produtos de e-commerce.

Casos de uso comuns de inteiros:

  • IDs (chaves primárias): user_id, product_id, order_id
  • Quantidades: estoque, quantidade_carrinho
  • Contadores: login_count, view_count, retry_count
  • Códigos de status: status_pedido (0 = pendente, 1 = pago, 2 = enviado …)
  • Flags booleanas: is_active, is_deleted (TINYINT com 0/1)

Não há motivo para usar DECIMAL ou FLOAT em nenhum desses casos. Inteiros são a escolha mais rápida e segura.

INT vs. BIGINT — “Melhor Prevenir” É Realmente Seguro?

O dilema mais comum na escolha de tipos inteiros é INT versus BIGINT. Resposta curta: INT é suficiente para a grande maioria dos casos de uso. A resposta longa mostra por que colocar BIGINT em tudo é um antipadrão caro.

Primeiro, vamos ter noção de escala. INT UNSIGNED suporta até 4,2 bilhões. A população do Brasil é de aproximadamente 215 milhões — apenas 5% da capacidade do INT. Um serviço web com 1 milhão de usuários poderia armazenar 4.000 registros de log por usuário e ainda ficaria dentro da faixa do INT. Para IDs de usuários, produtos e pedidos, INT quase sempre é mais que suficiente.

Então quando o BIGINT se torna necessário?

  • Logs de acesso: Um site com 100 milhões de page views por mês acumula 1,2 bilhão de linhas por ano. Em 3–4 anos, o teto do INT fica à vista
  • Dados de sensores IoT: 10.000 dispositivos enviando dados a cada segundo geram cerca de 315 bilhões de linhas por ano — muito além da faixa do INT
  • IDs distribuídos (Snowflake, etc.): Esses codificam timestamp, worker ID e número de sequência em um único valor que pode ser extremamente grande
  • IDs de transação: Um sistema de pagamento processando 1 milhão de transações por dia chega a 3,65 bilhões em 10 anos — perigosamente perto do limite superior do INT

Agora vamos quantificar o custo de “só coloca BIGINT em tudo”:

CenárioINT (4 bytes)BIGINT (8 bytes)Diferença
100M linhas × 1 coluna381 MB762 MB+381 MB
100M linhas × 1 col + 2 índices1,14 GB2,29 GB+1,14 GB
Memória de JOIN (estimado)Base~1,5–2×Menor eficiência de cache

Em uma tabela de 100 milhões de linhas, trocar uma única coluna mais dois índices de INT para BIGINT desperdiça mais de 1,1 GB. Multiplique isso por várias colunas e várias tabelas, e o total pode chegar a dezenas de gigabytes — tudo isso aumenta I/O de disco, reduz a eficiência do buffer pool e deixa as queries mais lentas.

Guia prático de decisão:

Finalidade da ColunaTipo RecomendadoJustificativa
ID de UsuárioINT UNSIGNEDPouquíssimos serviços ultrapassam 4,2 bilhões de usuários
ID de ProdutoINT UNSIGNEDMesma lógica
ID de PedidoINT UNSIGNED ou BIGINTDepende do volume e tempo de vida
ID de Log de AcessoBIGINTBilhões de linhas esperadas por ano
Snowflake / UUID NuméricoBIGINTValores inerentemente grandes
⚠️ Armadilha comum

Não baseie sua escolha apenas na contagem atual de linhas. O que importa é a taxa de crescimento ao longo de toda a vida operacional. Estime a quantidade anual de inserts, projete 10 anos à frente e verifique se INT UNSIGNED (4,2 bilhões) vai aguentar. Se não vai, comece com BIGINT desde o primeiro dia.

UNSIGNED — O Dobro da Faixa sem Custo Extra

No MySQL e MariaDB, adicionar UNSIGNED a uma coluna inteira remove a faixa negativa e dobra a faixa positiva sem custo adicional de armazenamento. Um INT regular vai de aproximadamente -2,1 bilhões a +2,1 bilhões; INT UNSIGNED vai de 0 a 4,2 bilhões — os mesmos 4 bytes.

Colunas como IDs, quantidades e contadores nunca são negativos. Não há motivo para não usar UNSIGNED nelas.

Exemplo de uso do UNSIGNED
CREATE TABLE users (n  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  age         TINYINT UNSIGNED,          u002du002d 0u0026lt;=255 é suficienten  login_count INT UNSIGNED DEFAULT 0,n  point       INT UNSIGNED DEFAULT 0n);
⚠️ Armadilha comum

Subtração entre duas colunas UNSIGNED pode causar underflow. No MySQL, SELECT a - b onde a < b produz um valor enorme (ou um erro) porque o resultado “dá a volta”. Se subtração for possível, use CAST(a AS SIGNED) - CAST(b AS SIGNED) ou considere manter a coluna como SIGNED.

Observação: PostgreSQL não suporta UNSIGNED. A solução comum é usar uma constraint CHECK (CHECK (id >= 0)) para garantir valores não-negativos no nível da aplicação.

DECIMAL (NUMERIC) — A Única Escolha Correta para Dinheiro

DECIMAL armazena números como valores exatos em base 10. Diferente do FLOAT, ele não converte para binário internamente, então 0,1 é armazenado como exatamente 0,1. Para qualquer coluna onde até uma fração de centavo importa — preços, notas fiscais, impostos, saldos — DECIMAL é o único tipo aceitável.

Por que não FLOAT? Veja o problema em ação:

Comparação de precisão: FLOAT vs DECIMAL
u002du002d O que acontece com FLOATnSELECT CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT);nu002du002d Resultado: 0.30000001192092896 (não é 0.3)nnu002du002d DECIMAL acertanSELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2));nu002du002d Resultado: 0.30 (exatamente 0.30)

Como esse erro minúsculo importa na prática? Imagine uma loja online vendendo um produto de R$ 59,90, processando 50.000 pedidos por mês:

  • Com FLOAT: Cada linha pode carregar um erro tão pequeno quanto +0,000001, mas ao longo de 50.000 linhas e múltiplos cálculos de ICMS, as discrepâncias de arredondamento se acumulam. Multiplique por centenas de SKUs ao longo de um ano, e o livro-caixa desvia por reais — o suficiente para disparar uma investigação de auditoria
  • Com DECIMAL: Zero desvio. Toda agregação bate no centavo, toda vez

“É só um milionésimo de real.” Verdade — mas em contabilidade, se os livros não fecham no centavo, alguém precisa explicar por quê. “Usamos o tipo de coluna errado” não é uma resposta que nenhum auditor vai aceitar.

DECIMAL é declarado como DECIMAL(M, D) onde M é o total de dígitos e D é o número de casas decimais:

DECIMAL na prática
u002du002d DECIMAL(10,2): 10 dígitos no total, 2 casas decimaisnu002du002d Valor máximo: 99.999.999,99nnCREATE TABLE pedidos (n  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  subtotal   DECIMAL(10,2) NOT NULL,  u002du002d Valor antes dos impostosn  aliquota   DECIMAL(5,4)  NOT NULL,  u002du002d Ex.: 0.1800 (ICMS 18%)n  imposto    DECIMAL(10,2) NOT NULL,  u002du002d Valor do imposton  total      DECIMAL(10,2) NOT NULL   u002du002d Total geraln);
💡 Dica

DECIMAL e NUMERIC são sinônimos no padrão SQL. MySQL, PostgreSQL e SQL Server tratam ambos de forma idêntica. Escolha um e mantenha a consistência em todo o seu código.

Dimensionando o DECIMAL — Por que DECIMAL(18,10) Quase Sempre É Exagero

Outro erro comum é especificar precisão excessiva: DECIMAL(18,10) ou até DECIMAL(30,15) “por precaução”. Isso desperdiça armazenamento e deixa agregações mais lentas.

O tamanho de armazenamento do DECIMAL é proporcional à quantidade de dígitos. No MySQL, cada 9 dígitos consomem 4 bytes, com bytes extras para os dígitos restantes:

TipoArmazenamento (MySQL)Exemplo de Uso
DECIMAL(5,2)3 bytesPercentuais (até 99,99%)
DECIMAL(10,2)5 bytesPreços (até R$ 99.999.999,99)
DECIMAL(12,4)6 bytesTaxas de câmbio (ex.: 5,3456)
DECIMAL(18,10)9 bytesExagero para a maioria das aplicações

A abordagem correta é raciocinar de trás para frente a partir do valor máximo:

  • Preços de e-commerce: Se o preço mais alto é de alguns milhões de reais, DECIMAL(10,2) cobre até R$ 99.999.999,99
  • Alíquotas de ICMS: No Brasil, alíquotas estaduais variam de 7% a 25%, podendo chegar a mais com ICMS-ST. DECIMAL(5,4) suporta até 99,9999%
  • Percentuais de desconto: 0–100% cabe em DECIMAL(5,2)
  • Taxas de câmbio: USD/BRL a 5,0845 — DECIMAL(12,4) fornece espaço de sobra
  • Criptomoedas: A menor unidade do Ethereum (wei = 10⁻¹⁸ ETH) genuinamente requer DECIMAL(36,18) — um caso raro onde precisão extrema é justificada

Usar DECIMAL(18,10) para uma coluna de preço de varejo é como imprimir um bilhete pessoal em papel A0. Dimensione a precisão corretamente e você vai economizar armazenamento e acelerar queries.

FLOAT / DOUBLE — Velocidade ao Custo da Exatidão

FLOAT e DOUBLE são tipos de ponto flutuante que representam decimais usando o formato binário IEEE 754. Isso lhes dá uma grande vantagem e uma limitação inerente.

A vantagem é clara: apenas 4 bytes (FLOAT) ou 8 bytes (DOUBLE) podem representar uma faixa enorme de valores. Só o FLOAT cobre ±3,4 × 10³⁸, e o hardware de ponto flutuante da CPU faz a aritmética extremamente rápida.

A limitação é que eles armazenam aproximações, não valores exatos. O decimal 0,1 se torna o binário infinitamente repetitivo 0,000110011001100… que precisa ser arredondado para caber em um número finito de bits. Essa é a causa raiz do famoso problema “0,1 + 0,2 ≠ 0,3”.

FLOAT é a escolha certa quando pequenos erros de arredondamento não afetam o resultado:

  • Leituras de temperatura: Um sensor industrial reporta 23,45 °C com precisão intrínseca de ±0,1 °C. Um erro de armazenamento de ±0,0001 °C é irrelevante
  • Coordenadas GPS: Seis casas decimais em latitude/longitude correspondem a ~11 cm de precisão. DOUBLE preserva até 15 dígitos significativos — precisão submilimétrica que vai muito além de qualquer necessidade real
  • Features de machine learning: Modelos de ML têm milhões a bilhões de parâmetros; arredondamento em nível micro em qualquer peso individual tem impacto desprezível na acurácia geral
  • Simulações físicas: Dinâmica de fluidos e análise estrutural dependem da velocidade do FLOAT, com o erro controlado no nível do algoritmo
  • Agregações estatísticas: Médias, desvios padrão e correlações são calculados a partir de dados que já contêm ruído estatístico

A escolha entre FLOAT e DOUBLE se resume a precisão e armazenamento:

TipoTamanhoDígitos SignificativosQuando Escolher
FLOAT4 bytes~7Sensível a armazenamento, dados de sensores
DOUBLE8 bytes~15Alta precisão necessária: GPS, computação científica

Armazenar coordenadas GPS como FLOAT dá apenas ~7 dígitos significativos — aproximadamente 11 m de precisão. Para uma aplicação de mapas, DOUBLE (~15 dígitos, sub-milimétrico) é a escolha óbvia. Por outro lado, armazenar leituras de sensores de temperatura como DOUBLE é inútil quando o próprio sensor tem precisão de apenas ±0,5 °C — FLOAT é mais que suficiente.

FLOAT vs. DECIMAL — Guia Rápido de Decisão

Na prática, você precisa tomar essa decisão rápido e com confiança. Aqui está uma tabela de referência:

Caso de UsoDECIMALFLOAT / DOUBLE
Preços, notas fiscais, faturamento✗ (nunca)
Alíquotas de ICMS, descontos
Pontos de fidelidade / milhas✓ (se fracionário)
Peso de estoque (kg)
Temperatura / umidade
Coordenadas GPS✓ (DOUBLE)
Dados de sensores
Features de ML / scores
Valores estatísticos (média, etc.)

A regra geral cabe em três linhas:

  • Envolve dinheiro → DECIMAL
  • Medição ou ciência → FLOAT / DOUBLE
  • Não tem certeza → DECIMAL (erre pelo lado seguro)

Memorize essas três regras e dificilmente vai errar.

Cinco Erros Comuns de Design

Erros de tipo numérico costumam ser invisíveis durante o desenvolvimento e só aparecem em produção. Aqui estão os cinco mais frequentes.

Erro 1: Colocar BIGINT em Toda Coluna

A mentalidade de “maior é mais seguro” leva equipes a colocar BIGINT como padrão em toda coluna inteira. Como mostrado acima, isso pode desperdiçar mais de 1 GB a cada 100 milhões de linhas em uma única coluna com índices. Em 10 tabelas com 3 colunas BIGINT cada, são aproximadamente 12 GB de armazenamento desperdiçado — impactando diretamente custos de hospedagem em nuvem e eficiência do buffer pool.

Erro 2: Usar FLOAT para Dinheiro

Este é o erro mais perigoso da lista. Muitas vezes passa em todos os testes unitários porque os erros de arredondamento são invisíveis em pequena escala. O problema aparece em produção quando o volume de transações cresce: “A receita mensal não bate com os depósitos reais no banco.” A análise de causa raiz leva dias, e corrigir retroativamente dados financeiros armazenados em FLOAT é extremamente difícil.

Erro 3: Superdimensionar a Precisão do DECIMAL

Definir DECIMAL(30,15) “por precaução” desperdiça armazenamento e deixa queries de agregação mais lentas. Fora criptomoedas (onde 18 casas decimais são genuinamente necessárias), pouquíssimos domínios de negócio precisam de mais de 4 casas decimais.

Erro 4: Não Prever o Overflow do INT

Uma tabela pode começar com apenas algumas centenas de inserts por dia, mas o crescimento pode ser exponencial. INT SIGNED suporta até ~2,1 bilhões. Com AUTO_INCREMENT a 50.000 inserts/dia, isso dá 117 anos de folga — mas dumps de dados de teste, gaps de ID e crescimento inesperado podem consumir essa margem mais rápido do que o esperado. Monitore regularmente os valores máximos de AUTO_INCREMENT.

Erro 5: Tipos Diferentes em JOINs

Se pedidos.user_id é INT mas users.id é BIGINT, cada JOIN dispara uma conversão implícita de tipo. No MySQL, isso pode impedir o otimizador de usar índices, transformando uma query de milissegundos em um full table scan de vários segundos. Sempre garanta que colunas usadas em JOINs tenham exatamente o mesmo tipo.

Tipos Recomendados por Caso de Uso

Use esta tabela de referência rápida ao projetar novas tabelas:

Finalidade da ColunaTipo RecomendadoObservações
ID de UsuárioINT UNSIGNED4,2 bilhões é mais que suficiente
ID de ProdutoINT UNSIGNEDMesma lógica
ID de Log / EventoBIGINT UNSIGNEDBilhões de linhas por ano
Snowflake IDBIGINTValores inerentemente grandes
Preço de produtoDECIMAL(10,2)Máximo R$ 99.999.999,99
Alíquota de ICMSDECIMAL(5,4)Ex.: 0.1800 (18%)
Percentual de descontoDECIMAL(5,2)Ex.: 15,50%
Taxa de câmbioDECIMAL(12,4)Ex.: 5,0845
Quantidade em estoque (inteiro)INT UNSIGNEDSem casas decimais
Peso (kg)DECIMAL(8,3)Ex.: 12345,678
TemperaturaFLOATPrecisão do sensor é suficiente
GPS lat / lngDOUBLEAlta precisão necessária
Feature de MLFLOATVelocidade acima de precisão
Pontos (inteiro)INT UNSIGNEDSem frações
Pontos (fracionário)DECIMAL(10,2)Milhas aéreas, etc.
Posição em rankingINT UNSIGNEDRankings nunca são negativos
Flag booleana (0/1)TINYINT UNSIGNEDBOOLEAN do MySQL por baixo dos panos
Código de statusTINYINT ou SMALLINTDimensione para a faixa de valores

Compartilhar uma tabela como essa com a equipe elimina a maioria dos debates sobre escolha de tipo durante o code review.

CREATE TABLE — Exemplos do Mundo Real

Por fim, aqui estão três definições de tabela prontas para produção. Observe como cada coluna usa o menor tipo adequado.

Exemplo 1: Produtos de E-commerce

produtos.sql
CREATE TABLE produtos (n  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  nome        VARCHAR(255) NOT NULL,n  preco       DECIMAL(10,2) NOT NULL DEFAULT 0.00,  u002du002d Dinheiro = DECIMALn  aliq_icms   DECIMAL(5,4) NOT NULL DEFAULT 0.1800, u002du002d 18% = 0.1800n  estoque     INT UNSIGNED NOT NULL DEFAULT 0,       u002du002d Quantidade inteiran  peso_kg     DECIMAL(8,3),                          u002du002d Peso para freten  avaliacao   FLOAT,                                 u002du002d Nota média dos usuáriosn  ativo       TINYINT UNSIGNED NOT NULL DEFAULT 1,   u002du002d Flag booleanan  criado_em   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMPn) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Exemplo 2: Logs de Acesso

logs_acesso.sql
CREATE TABLE logs_acesso (n  id          BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, u002du002d Alto volumen  user_id     INT UNSIGNED,               u002du002d Mesmo tipo de users.idn  status_code SMALLINT UNSIGNED NOT NULL,  u002du002d HTTP 200, 404, 500...n  resposta_ms INT UNSIGNED,                u002du002d Tempo de resposta em msn  criado_em   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,n  INDEX idx_user (user_id),n  INDEX idx_criado (criado_em)n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Exemplo 3: Leituras de Sensores IoT

leituras_sensores.sql
CREATE TABLE leituras_sensores (n  id            BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  dispositivo_id INT UNSIGNED NOT NULL,n  temperatura   FLOAT,          u002du002d Precisão do sensor é suficienten  umidade       FLOAT,          u002du002d Idemn  latitude      DOUBLE,         u002du002d GPS precisa de alta precisãon  longitude     DOUBLE,         u002du002d Idemn  bateria_pct   TINYINT UNSIGNED, u002du002d Bateria 0-100%n  registrado_em DATETIME(3) NOT NULL, u002du002d Precisão de milissegundosn  INDEX idx_disp_tempo (dispositivo_id, registrado_em)n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

As três tabelas compartilham um traço comum: cada coluna é definida com o menor tipo que atende ao seu propósito. IDs escalam com INT ou BIGINT conforme a necessidade, dinheiro usa DECIMAL, medições usam FLOAT/DOUBLE e flags usam TINYINT. É assim que um schema bem projetado se parece.

Resumo — Escolha de Tipo É Engenharia de Performance

Escolher um tipo numérico SQL não é apenas uma decisão de formatação. Afeta eficiência de armazenamento, performance de índices, velocidade de queries, precisão dos dados e escalabilidade futura — tudo ao mesmo tempo.

O essencial em quatro linhas:

  • Se cabe em inteiro, use um tipo inteiro (mais rápido, menor, zero erro)
  • INT para a maioria das colunas, BIGINT para logs de alto volume (o armazenamento dobra)
  • DECIMAL para dinheiro — sem exceções (erros de FLOAT são devastadores em finanças)
  • FLOAT / DOUBLE para ciência e medições (velocidade e faixa onde aproximação é aceitável)

Acima de tudo, o princípio orientador é: escolha o menor tipo que atende aos seus requisitos. Tipos superdimensionados desperdiçam armazenamento, reduzem eficiência de cache e deixam queries mais lentas. Tipos subdimensionados arriscam overflow. Acertar significa estimar a natureza dos seus dados (inteiro vs. decimal), a faixa de valores, a tolerância a erros e a taxa de crescimento ao longo da vida útil do sistema.

Design de tipos numéricos é um trabalho sem glamour, mas acertar desde o primeiro dia te poupa de degradação de performance, inchaço de armazenamento e incidentes em produção lá na frente. Toda vez que você escrever um CREATE TABLE, pergunte: “Esse tipo é realmente o adequado?” Só esse hábito já vai elevar a qualidade do design do seu banco de dados.

FAQ

P. Qual deve ser meu primeiro raciocínio quando não sei qual tipo usar?

R. Comece perguntando: “Esse valor pode ser representado como inteiro?” Se sim, vá de tipo INT. Depois pergunte: “Envolve dinheiro?” Se sim, DECIMAL é a única resposta. Todo o resto com casas decimais — temperaturas, coordenadas, scores — aponta para FLOAT ou DOUBLE. Siga essa sequência e 95% das decisões são instantâneas.

P. Migrar de INT para BIGINT depois é muito trabalhoso?

R. O ALTER TABLE ... MODIFY COLUMN do MySQL pode alterar o tipo, mas em tabelas grandes trava a tabela por minutos ou até horas. Ferramentas como pt-online-schema-change ou gh-ost fazem a migração com downtime quase zero, mas ainda exigem planejamento cuidadoso. Acertar o tipo desde o início é sempre mais barato do que refatorar depois.

P. O PostgreSQL não suporta UNSIGNED — o que devo fazer?

R. Correto. A abordagem padrão no PostgreSQL é usar uma constraint CHECK (CHECK (id >= 0)) para garantir valores não-negativos. Como o INT do PostgreSQL suporta até ~2,1 bilhões, é suficiente para a maioria das cargas de trabalho. Se você genuinamente precisa da faixa de 4,2 bilhões, mude para BIGINT.

P. O erro de arredondamento do FLOAT é tão ruim assim na prática?

R. FLOAT (4 bytes) tem cerca de 7 dígitos significativos. Armazene 123456,789 em FLOAT e você pode receber de volta 123456,7890625. Para dados de sensores ou medições científicas — onde o próprio instrumento tem precisão limitada — isso é irrelevante. Para cálculos financeiros, significa notas fiscais com erro de centavos e totais mensais que não fecham. A regra é simples: nunca use FLOAT para dinheiro.

P. DECIMAL é realmente mais lento que INT? Quanto?

R. Em queries pesadas de agregação (SUM, AVG sobre milhões de linhas), DECIMAL pode ser 1,2–2× mais lento que INT. Para cargas OLTP típicas — SELECTs e INSERTs individuais — a diferença é desprezível. Algumas equipes armazenam preços como centavos inteiros (ex.: R$ 19,99 → 1999) para ganhar a velocidade do INT, mas isso quebra no momento em que você precisa de suporte a múltiplas moedas ou cálculos sub-centavo. Começar com DECIMAL é a aposta mais segura a longo prazo.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *