PostgreSQL: Além do SQL Básico
PostgreSQL não é apenas um banco SQL — é um canivete suíço. Colunas JSON, busca full-text, window functions, CTEs e indexação JSONB significam que frequentemente você não precisa de Redis, Elasticsearch ou banco de analytics separado.
Tipos de Dados que Vale Conhecer
| Tipo | Caso de Uso | Exemplo |
|---|---|---|
uuid | Primary keys (melhor que serial para sistemas distribuídos) | gen_random_uuid() |
jsonb | Dados semi-estruturados (indexado, queryable) | {"tags": ["dev", "sql"]} |
text | Strings (sem limite, mesma performance que varchar) | Use text, não varchar |
timestamptz | Timestamps (sempre use COM timezone) | now() |
JSONB: O Document Store Dentro do Postgres
CREATE TABLE products (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
metadata jsonb DEFAULT '{}'
);
SELECT name, metadata->>'color' AS color
FROM products
WHERE metadata->>'category' = 'electronics';
CREATE INDEX idx_metadata ON products USING GIN (metadata);CTEs (Common Table Expressions)
WITH active_users AS (
SELECT id, name, email
FROM users
WHERE last_login > now() - interval '30 days'
)
SELECT u.name, COALESCE(o.order_count, 0) as orders
FROM active_users u
LEFT JOIN (
SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id
) o ON u.id = o.user_id;Window Functions
-- Ranking
SELECT name, total_spent,
RANK() OVER (ORDER BY total_spent DESC) as rank
FROM users;
-- Total acumulado
SELECT date, revenue,
SUM(revenue) OVER (ORDER BY date) as running_total
FROM daily_revenue;
-- Comparar com linha anterior
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) as prev_month
FROM monthly_revenue;Índices que Importam
-- B-tree (padrão)
CREATE INDEX idx_users_email ON users (email);
-- Índice parcial
CREATE INDEX idx_active_users ON users (email) WHERE active = true;
-- GIN (para JSONB, arrays, full-text)
CREATE INDEX idx_tags ON posts USING GIN (tags);
-- Verifique se a query usa o índice
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';Dicas de Performance
- Sempre use
EXPLAIN ANALYZE - Use
timestamptz, nuncatimestampsem timezone - Use
textao invés devarchar(n) - Adicione índices em foreign keys
- Use
UPSERT:INSERT ... ON CONFLICT DO UPDATE
Formate seu SQL: Formatador SQL — cole SQL bagunçado, obtenha saída formatada.