PostgreSQL: O que é e por que escolhê-lo

O PostgreSQL é o banco de dados relacional de código aberto mais avançado do mundo. Reconhecido por sua confiabilidade, extensibilidade e conformidade com padrões, ele é utilizado por líderes globais como Apple, Instagram e Spotify.

1. O Que Você Vai Aprender


2. A História Real de um Desenvolvedor Full-Stack

(1) O Problema: Escolher o Banco de Dados Gera Confusão

Alice é uma desenvolvedora full-stack cuja empresa está lançando um novo projeto de e-commerce. Na reunião de seleção de tecnologia, a equipe discutiu entre MySQL e PostgreSQL:

Ela precisava de uma comparação objetiva e abrangente para tomar a decisão.

(2) A Solução do PostgreSQL

O PostgreSQL cobre a maioria das necessidades de negócio com um único banco de dados — desde consultas relacionais tradicionais até armazenamento de documentos JSON, de busca textual a recuperação vetorial — sem middleware extra:

SQL
-- PostgreSQL: um banco de dados para múltiplos casos de uso

-- 1. Consulta relacional tradicional
SELECT u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.name;

-- 2. Armazenamento flexível JSONB (sem necessidade de MongoDB)
INSERT INTO products (name, attributes)
VALUES ('Running Shoes', '{"color": "red", "size": 42, "tags": ["sport", "outdoor"]}'::jsonb);

-- 3. Busca textual (sem necessidade de Elasticsearch)
SELECT name FROM products
WHERE to_tsvector('english', name) @@ to_tsquery('english', 'running & shoes');

(3) O Resultado

Alice percebeu que escolher o PostgreSQL significava:


3. O Que É um Banco de Dados

Um banco de dados é um sistema que organiza, armazena e gerencia dados de forma estruturada. Sem um banco de dados, os dados de uma aplicação só existem em memória — e desaparecem no momento em que o programa é fechado.

(1) Bancos de Dados Relacionais vs Não Relacionais

Dimensão Relacional (RDBMS) Não Relacional (NoSQL)
Modelo de dados Tabelas (linhas + colunas), esquema rígido Documento / chave-valor / grafo / colunar, esquema flexível
Linguagem de consulta SQL (padronizada) APIs proprietárias
Transações ACID, consistência forte Principalmente consistência eventual
Exemplos PostgreSQL, MySQL, Oracle MongoDB, Redis, Cassandra
Casos de uso Consultas complexas, processamento transacional, alta consistência Alta taxa de transferência, estrutura flexível, iteração rápida
Escalonamento Principalmente vertical Principalmente horizontal
100%
graph TB
    DB[Banco de Dados] --> RDBMS[Banco Relacional<br/>SQL + ACID]
    DB --> NoSQL[NoSQL<br/>Esquema Flexível]
    RDBMS --> PG[PostgreSQL]
    RDBMS --> MY[MySQL]
    RDBMS --> OR[Oracle]
    NoSQL --> MGO[MongoDB<br/>Documento]
    NoSQL --> RED[Redis<br/>Chave-Valor]
    NoSQL --> CAS[Cassandra<br/>Colunar]
💡 Tip: O PostgreSQL é um banco de dados relacional, mas seu tipo JSONB permite armazenar estruturas flexíveis como um banco de documentos — é por isso que o PG é chamado de "um banco de dados para substituir três."


4. Histórico do PostgreSQL

(1) Do POSTGRES ao PostgreSQL

100%
graph LR
    A["1986<br/>Projeto POSTGRES<br/>UC Berkeley"] --> B["1995<br/>Postgres95<br/>Adicionado suporte SQL"]
    B --> C["1996<br/>PostgreSQL 6.0<br/>Lançamento Open Source"]
    C --> D["2010s<br/>JSONB / CTE / Funções de<br/>Janela / FDW"]
    D --> E["2024<br/>PostgreSQL 17<br/>Versão LTS atual"]
Ano Marco Significado
1986 Projeto POSTGRES lançado Iniciado por Michael Stonebraker na UC Berkeley, inspirado pelo Ingres
1995 Postgres95 lançado Adicionado suporte à linguagem SQL (substituindo a linguagem de consulta PostQUEL)
1996 PostgreSQL 6.0 Renomeado oficialmente para PostgreSQL, lançado como código aberto
2005 Versão 8.0 Suporte nativo ao Windows, savepoints, commit em duas fases
2012 Versão 9.2 Suporte a JSON (atualizado para JSONB na 9.4), tipos de intervalo
2016 Versão 9.6 Consultas paralelas, busca textual por frase
2017 Versão 10.0 Particionamento declarativo, replicação lógica, autenticação SCRAM
2022 Versão 15.0 Comando MERGE (UPSERT padrão SQL)
2024 Versão 17.0 Versão LTS atual, replicação lógica aprimorada, padrão SQL/JSON completo

(2) Filosofia de Design do PostgreSQL

A filosofia central de design do PostgreSQL pode ser resumida em quatro palavras:

Princípio Materializado em
Conformidade com padrões Segue rigorosamente o padrão SQL (SQL:2023), suporta a maioria dos recursos padrão
Extensibilidade Suporta tipos personalizados, funções, métodos de índice e linguagens procedurais (via Extensions)
Confiabilidade Transações ACID, controle de concorrência MVCC, log write-ahead WAL — dados não são perdidos por padrão
Orientado à comunidade Nenhuma empresa única no controle; mais de 1000 contribuidores globais; verdadeiramente open source
📌 Key point: O PostgreSQL não é "PostgreSQL de alguém" — ele é mantido pelo PostgreSQL Global Development Group e não é controlado por nenhuma empresa. Isso contrasta fortemente com o MySQL (controlado pela Oracle).


5. PostgreSQL vs MySQL

Era disso que Alice e sua equipe mais se importavam. Aqui está uma comparação objetiva em várias dimensões:

Dimensão PostgreSQL MySQL
Arquitetura Modelo de processos (um processo por conexão) Modelo de threads (uma thread por conexão)
Concorrência MVCC (controle de concorrência multiversão); leituras e escritas não se bloqueiam Principalmente bloqueios de tabela; InnoDB bloqueia linhas mas com alcance limitado
Padrão SQL Segue rigorosamente o SQL:2023 Segue parcialmente; muitas sintaxes específicas do MySQL
Suporte a JSON JSONB (armazenamento binário, consultas indexadas muito rápidas) JSON (armazenamento de texto, recursos limitados)
Busca textual tsvector/tsquery nativo, suporte multilíngue Índice FULLTEXT, recursos básicos
Tipos de índice 6 tipos (B-Tree / GIN / GiST / BRIN / SP-GiST / Hash) 3 tipos (B-Tree / Hash / Fulltext)
Ecossistema de extensões CREATE EXTENSION instala recursos em uma etapa (pgvector / PostGIS, etc.) Sem mecanismo equivalente
Particionamento Particionamento declarativo (RANGE / LIST / HASH, PG 10+) Tabelas particionadas (8.0+), sintaxe mais verbosa
Replicação Replicação por streaming + lógica (replicar por tabela) Replicação mestre-escravo (instância inteira)
Backup PITR recuperação point-in-time (precisão de segundos) Replay de binlog (mais grosseiro)
Licença Licença PostgreSQL (estilo BSD, muito permissiva) GPL (restrições comerciais)
Consultas complexas Funções de janela / CTE recursiva / LATERAL JOIN suportados nativamente Suportado a partir da 8.0+ mas mais fraco que o PG
Operações Muitas opções de configuração, grande margem de ajuste Funciona pronto para uso, operações mais simples
Participação de mercado Banco de dados com crescimento mais rápido no DB-Engines por 7 anos consecutivos Maior base instalada global

▶ Exemplo: Comparação de Sintaxe UPSERT

SQL
-- PostgreSQL: INSERT ON CONFLICT (mais flexível)
INSERT INTO users (email, name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email)
DO UPDATE SET name = EXCLUDED.name, updated_at = NOW()
RETURNING id, name, updated_at;
-- A cláusula RETURNING retorna a linha afetada (MySQL não tem equivalente)

Output:

TEXT 📖 Somente leitura
INSERT 0 1
SQL
-- MySQL: ON DUPLICATE KEY UPDATE (menos flexível)
INSERT INTO users (email, name)
VALUES ('alice@example.com', 'Alice')
ON DUPLICATE KEY UPDATE name = VALUES(name), updated_at = NOW();
-- Sem cláusula RETURNING, é necessário executar um SELECT separado para obter o resultado

▶ Exemplo: Comparação de Consulta JSONB

SQL
-- PostgreSQL: JSONB com índice GIN (consultas indexadas rápidas)
SELECT name FROM products
WHERE attributes @> '{"color": "red"}'::jsonb;
-- @> é o operador "contém", utiliza índice GIN

Output:

TEXT 📖 Somente leitura
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)
SQL
-- MySQL: função JSON (sem suporte de índice para este padrão)
SELECT name FROM products
WHERE JSON_CONTAINS(attributes, '"red"', '$.color');
-- Sem índice, varredura completa da tabela

▶ Exemplo: Comparação de Busca Textual

SQL
-- PostgreSQL: busca textual nativa com ranqueamento
SELECT name, ts_rank(to_tsvector('english', name || ' ' || description),
                     to_tsquery('english', 'red & shoes')) AS rank
FROM products
WHERE to_tsvector('english', name || ' ' || description)
      @@ to_tsquery('english', 'red & shoes')
ORDER BY rank DESC;

Output:

TEXT 📖 Somente leitura
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)
SQL
-- MySQL: busca FULLTEXT básica (sem flexibilidade de ranqueamento)
SELECT name FROM products
WHERE MATCH(name, description) AGAINST('red shoes' IN BOOLEAN MODE);
⚠️ Note: O MySQL é mais fácil de aprender para cenários simples (CRUD de tabela única, projetos pequenos). O ponto forte do PostgreSQL está em consultas complexas, integridade de dados e recursos avançados. Escolha com base nas necessidades do projeto, não no hype.


6. Pontos Fortes do PostgreSQL

(1) Transações ACID

ACID é o conjunto de quatro propriedades que garantem a confiabilidade dos dados:

Propriedade Nome completo Significado Implementação no PostgreSQL
A Atomicidade Tudo ou nada: uma transação ou é totalmente bem-sucedida ou é totalmente revertida Log write-ahead WAL
C Consistência O banco de dados permanece em estado válido antes e depois de uma transação Restrições / triggers / verificações de tipo
I Isolamento Transações concorrentes não interferem entre si MVCC controle de concorrência multiversão
D Durabilidade Dados confirmados nunca são perdidos WAL + fsync

(2) MVCC Controle de Concorrência Multiversão

O MVCC é o núcleo da concorrência do PostgreSQL. Leituras não bloqueiam escritas e escritas não bloqueiam leituras:

Cenário MySQL (InnoDB) PostgreSQL (MVCC)
Concorrência leitura-escrita Bloqueios compartilhados/exclusivos, possível bloqueio Leitores veem um snapshot; escritores criam novas versões — sem bloqueio
Impacto de transação longa Bloqueia outras transações Sem bloqueio; apenas versões antigas são retidas
Leitura consistente Precisa de MVCC mas complexo de implementar Isolamento de snapshot natural

(3) Extensibilidade

O mecanismo de extensão do PostgreSQL (CREATE EXTENSION) é sua maior vantagem de ecossistema:

Extensão Função Substitui middleware
pgvector Busca vetorial / embeddings de IA Pinecone / Weaviate
PostGIS Consultas geoespaciais MongoDB Geo
pg_trgm Busca aproximada Elasticsearch
pgcrypto Funções de criptografia Criptografia na camada de aplicação
uuid-ossp Geração de UUID Geração na camada de aplicação
postgres_fdw Consultas entre bancos de dados Ferramentas de ETL

▶ Exemplo: Instalando e Usando Extensões

SQL
-- Verificar extensões disponíveis
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('uuid-ossp', 'pg_trgm', 'pgcrypto');

-- Instalar uma extensão
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Usar a extensão para gerar UUIDs
SELECT uuid_generate_v4();
-- Resultado: um UUID único como 550e8400-e29b-41d4-a716-446655440000

Output:

TEXT 📖 Somente leitura
CREATE TABLE

▶ Exemplo: Agregação Condicional com FILTER

SQL
-- PostgreSQL: cláusula FILTER para agregação condicional (padrão SQL)
SELECT
    store_id,
    COUNT(*) AS total_orders,
    COUNT(*) FILTER (WHERE status = 'completed') AS completed_orders,
    COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled_orders
FROM orders
GROUP BY store_id;

Output:

TEXT 📖 Somente leitura
 count 
-------
     5
(1 row)
SQL
-- MySQL: é necessário usar SUM(IF()) ou SUM(CASE) como solução alternativa
SELECT
    store_id,
    COUNT(*) AS total_orders,
    SUM(IF(status = 'completed', 1, 0)) AS completed_orders,
    SUM(IF(status = 'cancelled', 1, 0)) AS cancelled_orders
FROM orders
GROUP BY store_id;

7. Casos de Uso Comuns do PostgreSQL

Cenário Recurso do PG Exemplo
E-commerce Atributos de produto JSONB + busca textual + particionamento Atributos dinâmicos de SKU, busca de produtos, pedidos particionados por mês
SaaS multi-tenant RLS segurança em nível de linha + isolamento de esquema Um banco de dados atendendo muitos tenants, políticas de linha isolam dados
Análise de dados Funções de janela + visões materializadas + CTE Análise de retenção de usuários, relatórios de tendência de vendas, estatísticas complexas
IA / recomendação Busca vetorial pgvector Similaridade de produtos, busca semântica, aplicações RAG
Serviços GIS Extensão PostGIS Aplicações de mapa, cálculo de distância, planejamento de rotas
Finanças ACID + 3 níveis de isolamento + PITR Transferências, conciliação, recuperação point-in-time
Gestão de conteúdo Busca textual + JSONB Busca de artigos, gestão de tags, conteúdo flexível

▶ Exemplo: E-commerce — JSONB para Atributos de Produto

SQL
-- Produtos diferentes têm atributos diferentes
-- Sem necessidade de tabelas ou colunas separadas para cada tipo de atributo

INSERT INTO products (name, price, attributes) VALUES
    ('Running Shoes', 89.99, '{"color": "red", "size": 42, "weight_grams": 280}'::jsonb),
    ('Laptop', 1299.00, '{"cpu": "M3", "ram_gb": 16, "screen_inch": 14}'::jsonb),
    ('Coffee Beans', 24.50, '{"origin": "Colombia", "roast": "medium", "weight_kg": 1}'::jsonb);

-- Consulta: encontrar todos os produtos vermelhos abaixo de $100
SELECT name, price, attributes
FROM products
WHERE price < 100
  AND attributes @> '{"color": "red"}'::jsonb;

Output:

TEXT 📖 Somente leitura
     name      | price  |                 attributes
---------------+--------+--------------------------------------------
 Running Shoes |  89.99 | {"color": "red", "size": 42, "weight_grams": 280}

8. Exemplo Completo: Fluxo de Decisão de Seleção de Banco de Dados

SQL
-- ============================================
-- Exemplo abrangente: demonstração de recursos do PostgreSQL
-- Mostra por que um banco de dados PG pode substituir múltiplas ferramentas
-- ============================================

-- 1. Transação ACID (sem necessidade de consistência na camada de aplicação)
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT;

-- 2. Armazenamento JSONB (sem necessidade de MongoDB)
INSERT INTO products (name, attributes)
VALUES ('Smart Watch', '{"color": "black", "battery_life_hours": 48, "waterproof": true}'::jsonb);

-- 3. Busca textual (sem necessidade de Elasticsearch)
SELECT name, ts_rank(
    to_tsvector('english', name),
    plainto_tsquery('english', 'smart watch')
) AS relevance
FROM products
WHERE to_tsvector('english', name) @@ plainto_tsquery('english', 'smart watch')
ORDER BY relevance DESC;

-- 4. Função de janela (sem necessidade de ranqueamento na camada de aplicação)
SELECT name, price,
    RANK() OVER (ORDER BY price DESC) AS price_rank
FROM products;

-- 5. UPSERT (sem necessidade de tratamento de conflito na camada de aplicação)
INSERT INTO products (name, price, attributes)
VALUES ('Smart Watch', 199.99, '{"color": "black", "battery_life_hours": 48}'::jsonb)
ON CONFLICT (name)
DO UPDATE SET price = EXCLUDED.price,
              attributes = EXCLUDED.attributes
RETURNING id, name, price;

Output (excerpt):

TEXT 📖 Somente leitura
 -- Resultado do UPSERT RETURNING:
 id |    name     | price
----+-------------+--------
  1 | Smart Watch | 199.99

❓ Perguntas Frequentes

P: O PostgreSQL é completamente gratuito? Existe alguma licença comercial oculta? R: O PostgreSQL usa a Licença PostgreSQL (estilo BSD), então você pode usar, modificar e distribuir livremente — inclusive comercialmente — sem taxas ocultas. É mais permissiva que a GPL do MySQL: você nem precisa abrir o código da sua aplicação.

P: O PostgreSQL é adequado para projetos pequenos? Não é muito pesado? A: Uma instalação mínima do PostgreSQL roda com cerca de 50 MB de memória. Para projetos pequenos, o modo de configuração zero do PG funciona pronto para uso. Comparado ao MySQL, os padrões do PG já são seguros e confiáveis — projetos pequenos não sentirão que é "muito pesado."

P: Devo escolher PostgreSQL ou MySQL? R: Escolha PostgreSQL se seu projeto precisa de consultas complexas, JSONB, busca textual, GIS ou escritas de alta concorrência. MySQL é adequado se seu projeto é CRUD simples, sua equipe só conhece MySQL ou você precisa de desempenho máximo de leitura. Desde 2024, a proporção de novos projetos escolhendo PostgreSQL continua aumentando.

P: Migrar do MySQL para o PostgreSQL é difícil? R: Para projetos de pequeno a médio porte, a migração leva cerca de 1–2 semanas. A maior parte do trabalho são diferenças de sintaxe SQL (ex.: backticks → aspas duplas, AUTO_INCREMENT → SERIAL/IDENTITY). Para ferramentas, o pgLoader pode migrar dados e esquema automaticamente.

P: O PostgreSQL é realmente mais rápido que o MySQL? R: Em cenários OLTP (leitura/escrita simples), os dois são próximos. Em escritas de alta concorrência, JOINs complexos, funções de janela e consultas JSONB, o PostgreSQL supera claramente o MySQL. O MVCC do PG mantém leituras e escritas sem bloqueio mútuo — essa é a vantagem central.

P: Preciso aprender MySQL antes do PostgreSQL? A: Não. O SQL do PostgreSQL é mais próximo do SQL padrão, então aprender PG primeiro é na verdade melhor. Uma vez que você conhece PG, o MySQL parece fácil (porque o PG ensina mais sintaxe padrão).


📖 Resumo


📝 Exercícios

  1. Básico (★): Liste 3 recursos que tornam o PostgreSQL único em comparação com o MySQL (recursos que o MySQL não possui ou onde é significativamente mais fraco) e explique em uma frase o benefício de cada um.

  2. Intermediário (★★): Suponha que você está escolhendo um banco de dados para uma plataforma de educação online que precisa armazenar informações de cursos (estruturadas) e anotações de alunos (não estruturadas), além de buscar conteúdo de cursos. Escreva sua razão para escolher PostgreSQL ou MySQL, citando pelo menos 3 recursos técnicos para apoiar seu argumento.

  3. Desafio (★★★): Leia a página "Feature Matrix" da documentação do PostgreSQL (busque "PostgreSQL Feature Matrix") e encontre 3 recursos do PG não mencionados nesta lição, explicando qual ferramenta externa ou middleware cada um pode substituir.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%