Primeiro tijolo da trilha. Foco: você consegue olhar pra um schema de banco de cliente e fazer 3 perguntas relevantes antes de propor qualquer integração. Não vamos te ensinar a escrever queries complexas; vamos te ensinar a LER e fazer as perguntas certas.
Pré-requisito: nenhum. Tempo estimado: 3-4 horas de leitura + 1 hora de exercício. Output prático: você sustenta 20 min de conversa sobre banco de dados sem virar passageiro.
Por que essa semana importa
Em 9 de 10 discoveries do Team Studio, alguém da empresa-cliente vai mencionar: - "Nosso CRM tá no SQL Server" - "Os dados de venda ficam no nosso data warehouse Snowflake" - "Temos uma tabela de 50 milhões de registros com performance ruim" - "Não pode mexer no banco de produção"
Sem repertório, você fica em uma de duas posições ruins: 1. Fingir que entende - entrega errada de proposta, frustração pra todos 2. Admitir total ignorância - perde credibilidade, cliente decide que você não é parceiro técnico, vira só fornecedor
Você não precisa virar DBA. Precisa entender o suficiente pra: - Saber o que perguntar - Avaliar se a resposta faz sentido - Identificar quando alguém complica pra justificar mais escopo
Essa semana destrava isso.
1. O que é um banco relacional, em 3 frases
Banco relacional armazena dados em tabelas, que são parecidas com planilhas: têm colunas (campos: nome, email, valor) e linhas (registros: cada cliente, cada pedido). Tabelas se relacionam entre si por chaves - uma coluna em uma tabela aponta pra outra tabela ("esse pedido pertence ao cliente 123"). Operações no banco são feitas com a linguagem SQL, que tem 4 verbos básicos: SELECT (ler), INSERT (criar), UPDATE (atualizar), DELETE (apagar).
Isso é 90% do que você precisa entender pra começar.
2. Anatomia de uma tabela
Exemplo: tabela clientes numa empresa qualquer.
| id | nome | telefone | cidade | created_at | |
|---|---|---|---|---|---|
| 1 | Ana Silva | ana@email.com | (11) 99999-1111 | São Paulo | 2024-01-15 |
| 2 | Bruno Costa | bruno@email.com | (21) 88888-2222 | Rio de Janeiro | 2024-02-03 |
| 3 | Carla Dias | carla@email.com | (31) 77777-3333 | Belo Horizonte | 2024-02-10 |
Conceitos:
- Colunas (fields): id, nome, email, telefone, cidade, created_at
- Linhas (rows/records): cada cliente é uma linha
- Tipo de dado: cada coluna tem tipo definido - id é integer, nome é varchar (texto), created_at é timestamp
- Chave primária (Primary Key, PK): a id é única e identifica cada linha. Toda tabela tem uma.
- NULL vs NOT NULL: algumas colunas aceitam vazio (telefone pode), outras não (email provavelmente obrigatório).
Pergunta de reunião que isso destrava:
"Qual é a primary key dessa tabela? E qual a estratégia: auto-increment, UUID, ou natural key?"
Você não precisa entender as 3 respostas profundamente. Mas perguntar isso te coloca como par técnico, não como vendedor.
3. Como tabelas se relacionam: chaves estrangeiras
Outra tabela: pedidos.
| id | cliente_id | valor | status | created_at |
|---|---|---|---|---|
| 100 | 1 | 250.00 | pago | 2024-03-01 |
| 101 | 1 | 480.50 | pago | 2024-03-15 |
| 102 | 2 | 1200.00 | pendente | 2024-03-20 |
Veja a coluna cliente_id. Ela é uma chave estrangeira (Foreign Key, FK) que aponta pra clientes.id. Significa: "esse pedido foi feito pelo cliente cuja id é X".
Pedido 100 foi da Ana (cliente_id=1, e Ana tem id=1 na tabela clientes).
Pedido 102 foi do Bruno (cliente_id=2).
Isso é a essência do "banco relacional": dados separados em tabelas que se conectam por chaves.
Diagrama ER (Entity-Relationship) é a representação visual disso. Você vai ver algo assim:
┌─────────────────┐ ┌─────────────────┐
│ clientes │ │ pedidos │
├─────────────────┤ ├─────────────────┤
│ id (PK) │◄────────│ cliente_id (FK) │
│ nome │ 1:N │ id (PK) │
│ email │ │ valor │
│ telefone │ │ status │
│ cidade │ │ created_at │
│ created_at │ └─────────────────┘
└─────────────────┘
O 1:N significa "um pra muitos" - um cliente pode ter muitos pedidos, mas cada pedido tem só um cliente.
Outros tipos de relação:
- 1:1 - um pra um (raro): um usuário tem um perfil, um perfil pertence a um usuário
- 1:N - um pra muitos (mais comum): um cliente tem muitos pedidos
- N:N - muitos pra muitos: produtos e pedidos (um pedido tem vários produtos, um produto está em vários pedidos). Sempre exige tabela intermediária (pedido_itens).
Pergunta de reunião:
"Vocês têm um diagrama ER atualizado do schema? Senão, dá pra rodar um schema introspection rápido com
pg_dump --schema-onlyou similar?"
Quem trabalha com banco tem como gerar isso em 5 minutos. Se gaguejarem, é sinal de que schema está caótico - sinal importante pra você precificar maior.
4. SQL essencial - só o suficiente pra ler
Você não precisa escrever queries do zero. Mas precisa entender quando alguém te mostrar uma. Os 5 padrões que cobrem 80% do que você vai encontrar:
4.1 SELECT básico
SELECT nome, email FROM clientes WHERE cidade = 'São Paulo';
Traduz pra: "me dá nome e email de todos os clientes da tabela clientes onde a cidade for São Paulo".
SELECT: o que quero verFROM: de qual tabelaWHERE: condição de filtro
4.2 JOIN - combinando tabelas
SELECT c.nome, p.valor, p.created_at
FROM clientes c
JOIN pedidos p ON p.cliente_id = c.id
WHERE p.status = 'pago';
Traduz pra: "me dá o nome do cliente e o valor de cada pedido pago, juntando as duas tabelas pelo cliente_id".
O JOIN é onde tabela clientes e tabela pedidos se conectam pra te dar uma resposta unificada.
Tipos de JOIN (você só precisa reconhecer):
- INNER JOIN (ou só JOIN): só registros que estão nas duas tabelas
- LEFT JOIN: todos da esquerda + os matches da direita (NULL se não tiver match)
- RIGHT JOIN: oposto (raro)
- FULL OUTER JOIN: todos dos dois lados (raro)
4.3 GROUP BY - agregando
SELECT cliente_id, COUNT(*) as total_pedidos, SUM(valor) as total_gasto
FROM pedidos
WHERE status = 'pago'
GROUP BY cliente_id;
Traduz pra: "me dá, por cliente, quantos pedidos pagos ele tem e o total gasto".
GROUP BY agrupa linhas. COUNT(), SUM(), AVG(), MAX(), MIN() são as funções de agregação mais comuns.
4.4 ORDER BY e LIMIT - ordenando e limitando
SELECT nome, email FROM clientes
ORDER BY created_at DESC
LIMIT 10;
Traduz pra: "me dá os 10 clientes mais recentes".
DESC é decrescente, ASC é crescente (default).
4.5 Subquery / CTE - query dentro de query
WITH top_clientes AS (
SELECT cliente_id, SUM(valor) as total
FROM pedidos
WHERE status = 'pago'
GROUP BY cliente_id
ORDER BY total DESC
LIMIT 100
)
SELECT c.nome, c.email, t.total
FROM top_clientes t
JOIN clientes c ON c.id = t.cliente_id;
Traduz pra: "primeiro, encontra os 100 clientes que mais gastaram (resultado tá na 'tabela temporária' top_clientes); depois, me dá o nome e email deles".
CTE (Common Table Expression) com WITH é forma moderna de fazer subquery. Você vai ver MUITO.
5. Normalização - o que é, e quando desnormalizar
Normalização é o processo de organizar tabelas pra evitar redundância de dados. Tem 3 níveis principais (formas normais).
5.1 1NF (Primeira Forma Normal)
Cada coluna armazena 1 valor atômico, não lista ou estrutura.
❌ Errado (não está em 1NF): | id | cliente | telefones | |---|---|---| | 1 | Ana | (11) 99999, (11) 88888 |
✅ Certo (está em 1NF, telefones viraram tabela separada):
Tabela clientes:
| id | nome |
|---|---|
| 1 | Ana |
Tabela cliente_telefones:
| cliente_id | telefone |
|---|---|
| 1 | (11) 99999 |
| 1 | (11) 88888 |
5.2 2NF (Segunda Forma Normal)
Cada coluna não-chave depende da chave inteira (não de parte dela). Aplica quando você tem chave composta.
Você vai raramente ouvir falar em 2NF na prática - geralmente é coberto se você seguir 1NF e 3NF.
5.3 3NF (Terceira Forma Normal)
Cada coluna não-chave depende só da chave, não de outra coluna não-chave.
❌ Errado (cidade depende de cep, não de cliente_id): | id | nome | cep | cidade | estado | |---|---|---|---|---| | 1 | Ana | 01000-000 | São Paulo | SP |
✅ Certo (cep, cidade, estado viram tabela separada enderecos):
Tabela clientes:
| id | nome | endereco_id |
|---|---|---|
| 1 | Ana | 1 |
Tabela enderecos:
| id | cep | cidade | estado |
|---|---|---|---|
| 1 | 01000-000 | São Paulo | SP |
5.4 Quando NÃO normalizar (desnormalização intencional)
Normalização ajuda escrita (você atualiza endereço em 1 lugar e tudo segue), mas atrapalha leitura (toda query precisa de JOIN). Em sistemas que LÊEM MUITO MAIS do que escrevem, vale desnormalizar algumas tabelas.
Casos comuns de desnormalização:
- Data warehouse: feito pra análise. Normalizar destrói performance. Esquema "star schema" / "snowflake" é parcialmente desnormalizado de propósito.
- Cache de dado calculado: você guarda total_pedidos direto na tabela clientes em vez de calcular toda vez. Acaba ficando 1 dia desatualizado, mas é mil vezes mais rápido pra ler.
- Materialized views: tabela que guarda resultado de query complexa, atualizada periodicamente.
Pergunta de reunião:
"Esse schema é normalizado ou tem desnormalização intencional? Quais tabelas têm dados redundantes pra performance?"
A resposta vai te dizer muito sobre maturidade do banco do cliente.
6. Index - o herói invisível
Imagine um livro de 1000 páginas sem índice no fim. Pra encontrar a palavra "marketing", você lê página por página, até achar. Slow as hell.
Com índice no fim do livro, você vê "marketing → página 347". Vai direto.
No banco, index funciona igual. É uma estrutura separada que mapeia valores de uma coluna pra "onde está cada linha".
6.1 Como índice acelera
-- Sem índice em 'email':
SELECT * FROM clientes WHERE email = 'ana@email.com';
-- Banco lê TODAS as linhas (10 milhões) procurando essa.
-- Demora 30 segundos.
-- Com índice em 'email':
SELECT * FROM clientes WHERE email = 'ana@email.com';
-- Banco usa o índice, vai direto na linha.
-- Demora 5 milissegundos.
Diferença de 6000x. Não é exagero.
6.2 Por que não indexar tudo
Cada índice: - Ocupa espaço em disco (pode ser 10-30% do tamanho da tabela) - Atrasa INSERTs/UPDATEs/DELETEs (toda escrita precisa atualizar o índice também) - Precisa ser mantido (rebalanceamento, vacuum, etc)
Regra prática: indexar colunas que aparecem em WHERE, JOIN, ORDER BY. Não indexar tudo.
6.3 Tipos de índice (você só precisa reconhecer nomes)
- B-tree (padrão): bom pra =, <, >, BETWEEN, LIKE 'prefix%'
- Hash: bom pra = exata (Postgres usa raramente)
- GIN: bom pra full-text search, arrays, JSONB
- GiST: bom pra geoespacial, ranges
- Partial index: índice só pra subset de linhas (ex:
WHERE active = true) - Composite index: índice em múltiplas colunas
6.4 EXPLAIN - o raio-X de query
EXPLAIN ANALYZE
SELECT c.nome, COUNT(p.id) FROM clientes c
JOIN pedidos p ON p.cliente_id = c.id
GROUP BY c.id;
EXPLAIN ANALYZE mostra o plano de execução do banco: quais índices usa, quanto tempo cada passo levou. É a ferramenta principal de DBA pra otimizar.
Você não precisa ler EXPLAIN sozinho. Mas se um DBA mostra um EXPLAIN dizendo "está fazendo Seq Scan ao invés de Index Scan", isso significa que falta índice e a query tá lenta.
Pergunta de reunião:
"Vocês usam EXPLAIN regularmente pra revisar queries? Tem alguma rotina de revisão de índices?"
Empresa madura tem rotina. Empresa imatura "só cria índice quando dá problema".
7. Cinco perguntas que você consegue fazer agora
Após essa semana, em qualquer reunião com cliente sobre banco de dados, você pode perguntar:
7.1 "Qual o tamanho atual da base?"
Por que importa: 100k registros vs 100 milhões vs 100 bilhões mudam ARQUITETURA inteira. Cliente que diz "temos um banco grande" sem número é cliente que não mediu.
7.2 "Vocês têm um diagrama ER atualizado? Quantas tabelas centrais (não auxiliares)?"
Por que importa: 10 tabelas centrais = sistema simples. 200 = sistema complexo, vai exigir mais escopo. 500+ = empresa madura ou caos histórico.
7.3 "Qual a estratégia de chaves primárias? Sequential, UUID, ou natural keys?"
Por que importa: revela maturidade. UUID é moderno, mas tem custo. Sequential é tradicional. Natural key é raro e geralmente significa problema futuro.
7.4 "O schema é normalizado ou tem desnormalização proposital?"
Por que importa: revela se o sistema é OLTP (operacional, normalizado) ou OLAP (analítico, desnormalizado) ou híbrido. Muda como Team Studio vai integrar.
7.5 "Tem performance ruim em alguma área específica? Vocês fazem revisão regular de índices?"
Por que importa: revela onde a dor real está. Cliente que diz "tem problema no relatório de venda" tá te dando o caminho pro Team Studio entregar valor visível rápido.
Bônus de pergunta sofisticada:
"Tem RLS (Row Level Security) configurada em alguma tabela? Como vocês isolam dados de tenants diferentes?"
Se cliente é SaaS B2B, essa pergunta é OURO. Mostra que você entende o problema dele em profundidade.
8. Exercício prático
Imagine que cliente Team Studio te mostra esse schema:
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ empresas │ │ funcionarios │ │ departamentos │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ id (PK) │◄────────│ empresa_id (FK) │ │ id (PK) │
│ razao_social │ 1:N │ depto_id (FK) │────────►│ empresa_id (FK) │
│ cnpj │ │ id (PK) │ N:1 │ nome │
│ created_at │ │ nome │ │ created_at │
└──────────────────┘ │ email │ └──────────────────┘
│ cargo │
│ salario │
│ created_at │
└──────────────────┘
Pratique fazer 3 perguntas relevantes pro cliente sobre esse schema.
Exemplo de perguntas boas:
1. "Quantas empresas estão na base? E qual a média de funcionários por empresa?"
2. "A coluna salario é dado sensível (LGPD). Quem tem acesso a essa tabela? Tem RLS configurada?"
3. "O cargo é texto livre ou tem tabela cargos separada? Se é texto livre, vocês têm problema de inconsistência (Dev vs Desenvolvedor vs Programador)?"
Exemplo de perguntas ruins (que mostram desconhecimento): - "Como faço pra consultar essa tabela?" (revela que você não sabe SQL básico) - "Por que tem 3 tabelas?" (revela que você não entende normalização) - "Qual o melhor banco?" (pergunta vazia, sem contexto)
Anote 3 perguntas suas pra calibrar antes da próxima reunião com TI corporativo.
9. Material extra (opcional)
Se quiser aprofundar, sem virar dev:
Livros (acessíveis): - "SQL Antipatterns" (Bill Karwin) - capítulos curtos sobre erros comuns, ótimo pra aprender pelo "como NÃO fazer" - "Designing Data-Intensive Applications" (Martin Kleppmann) - cap 1-3 são leitura genial pra dono técnico (cap 4+ é pra dev)
Vídeos: - "SQL Tutorial - Full Database Course for Beginners" (freeCodeCamp, 4h) - só ver até a parte de JOIN é suficiente - "Postgres CRUD Operations" - busca no YouTube, qualquer série de 3 vídeos
Brincar com SQL sem instalar nada: - https://sqlfiddle.com (sandbox grátis) - https://www.db-fiddle.com (idem, suporta múltiplos bancos)
Cria uma tabela clientes, insere 10 linhas, faz 5 queries simples. 30 minutos brincando vai te dar mais intuição que 3 horas lendo teoria.
10. Próxima semana
A Semana 2 continua o Bloco A (Dados) com NoSQL e CAP theorem em português: 4 famílias NoSQL (documento, chave-valor, coluna larga, grafo), casos onde NoSQL é solução vs onde virou modinha, ACID vs BASE, eventual consistency, onda "back to Postgres" que cresceu desde 2020. Inclui cenário startup com 4 NoSQLs e over-engineering.