Primeira pergunta: por que a gente trabalha com JSONB afinal? JSONB permite guardar dados no formato JSON, deixando a estrutura bem flexível. Isso é super útil quando os dados têm relações complexas e aninhadas (tipo perfis de usuários com uma lista de endereços ou configurações). Diferente do JSON simples, o JSONB guarda os dados em formato binário, o que deixa as buscas e filtros muito mais rápidos.
Mas sem índices, buscar em JSONB pode ser bem lento, principalmente se a tabela tiver milhares ou milhões de linhas. Imagina que a gente tem uma tabela com informações de usuários, onde guardamos as configurações de cada um em um campo JSONB. Tentar achar todos os usuários com um valor específico nessas configs sem índice — é pedir pra gastar recurso à toa. É aí que entram nossos índices!
Indexando JSONB: pontos importantes
Pra trabalhar com JSONB, o PostgreSQL suporta indexação de dois jeitos principais:
- GIN (Generalized Inverted Index) — pra buscar por chaves e valores dentro do
JSONB. - BTREE — pra buscas e ordenações mais simples.
Cada um tem suas particularidades. Bora entender melhor cada um deles.
Índice GIN para JSONB
GIN é um índice poderoso, que funciona com arrays, textos e também com dados JSONB. Ele "quebra" o conteúdo do objeto JSONB em chaves e valores separados, criando uma estrutura especial pra buscar tudo isso rapidinho.
Vantagens do GIN pra JSONB:
- Permite buscar tanto por chaves quanto por valores.
- Funciona com estruturas aninhadas.
- Acelera operações com os operadores
@>,?,?|,?&(filtrando chaves e valores).
Imagina que a gente tem uma tabela users, onde a coluna settings guarda as configs dos usuários em JSONB. Exemplo de dados:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT,
settings JSONB
);
INSERT INTO users (name, settings) VALUES
('Alice', '{"tema": "escuro", "notificacoes": {"email": true, "sms": false}}'),
('Bob', '{"tema": "claro", "notificacoes": {"email": false, "sms": true}}'),
('Charlie', '{"tema": "escuro", "notificacoes": {"email": true, "sms": true}}');
Agora a gente quer achar rapidinho todos os usuários com tema escuro (tema: escuro). Primeiro, vamos criar o índice:
CREATE INDEX idx_users_settings_gin ON users USING GIN (settings);
Depois, faz a consulta usando o operador @> (busca por valor):
SELECT name
FROM users
WHERE settings @> '{"tema": "escuro"}';
Agora o PostgreSQL usa o índice GIN pra buscar, e a consulta fica bem mais rápida.
Como isso funciona? Quando você cria um índice GIN na coluna JSONB, o PostgreSQL monta um índice "invertido", ou seja, cria registros separados pra todas as chaves e valores do JSON. Por exemplo, do objeto:
{"tema": "escuro", "notificacoes": {"email": true, "sms": false}}
ele vai indexar as chaves tema, notificacoes.email, notificacoes.sms e seus valores. Isso deixa a busca por cada elemento bem mais rápida.
Índice BTREE para JSONB
BTREE é o índice clássico. Ele é usado quando você precisa comparar objetos JSONB inteiros ou fazer ordenação. Mas, diferente do GIN, o BTREE não quebra o conteúdo do JSON.
Vantagens do BTREE pra JSONB:
- Ótimo pra operações de ordenação e comparação de objetos.
- Funciona mais rápido se o
JSONBé usado como "monolito" (tipo, você compara ele inteiro com outro objeto ou procura linhas onde oJSONBé igual a um valor específico).
Vamos ver um exemplo de uso do índice BTREE. Imagina que na tabela users a gente quer comparar bastante a coluna settings com um objeto específico:
{"tema": "escuro", "notificacoes": {"email": true, "sms": false}}
Primeiro, cria o índice:
CREATE INDEX idx_users_settings_btree ON users USING BTREE (settings);
Agora dá pra fazer consultas comparando objetos:
SELECT name
FROM users
WHERE settings = '{"tema": "escuro", "notificacoes": {"email": true, "sms": false}}';
Essa consulta vai usar o índice BTREE pra acelerar.
Comparando GIN e BTREE
| Característica | GIN |
BTREE |
|---|---|---|
Quebra do objeto JSONB |
Sim, quebra em chaves e valores | Não, compara inteiro |
| Busca em estruturas aninhadas | Sim | Não |
| Ordenação | Não | Sim |
| Tamanho do índice | Maior | Menor |
| Operadores suportados | @>, ?, ?|, ?& |
= |
Então, GIN é melhor pra consultas mais complexas, enquanto BTREE é útil quando você precisa comparar objetos inteiros ou ordenar.
Qual índice escolher?
- Se você quer buscar por chaves e valores dentro do
JSONB, vai deGIN. - Se precisa comparar ou ordenar objetos
JSONBinteiros,BTREEé melhor.
Mas lembra: ninguém te impede de combinar esses índices! Por exemplo, dá pra criar tanto GIN quanto BTREE no mesmo campo, se a tabela precisar dos dois tipos de consulta.
Erros comuns ao indexar JSONB
Criar índices desnecessários: nem sempre vale a pena indexar todo campo JSONB. Índices ocupam espaço e podem deixar mais lentas as operações de insert e update.
Indexar operadores pouco usados: não indexa um campo só porque parece "certo". Analisa as consultas e só usa índice onde realmente acelera as operações.
Ignorar as particularidades do GIN: GIN pode demorar mais pra criar o índice do que BTREE. Isso é importante em tabelas grandes.
Aplicação prática
Trabalhar com JSONB é útil em projetos reais, onde os dados são flexíveis e mudam bastante. Por exemplo:
- Apps web com configs de usuário.
- Guardar logs, que têm campos diferentes pra cada evento.
- Cache de dados em formato JSON.
Indexar esses dados com GIN e BTREE ajuda muito a melhorar a performance das consultas. Tipo, numa entrevista de emprego, você pode mostrar como acelerou o sistema adicionando índices pra estruturas de dados complexas.
A documentação oficial do PostgreSQL sobre índices JSON tá disponível aqui. Não esquece de dar uma olhada lá pra tirar dúvidas e ver exemplos.
GO TO FULL VERSION