System Design/02 - Componentes/Databases2 min
Graph Databases
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Modelam nós, arestas e propriedades, com travessia de relacionamentos como operação nativa.
(Ana)-[:AMIGO_DE]->(Bruno)-[:AMIGO_DE]->(Carla)
(Ana)-[:COMPROU]->(Produto)<-[:COMPROU]-(Carla)
Exemplos: Neo4j, Amazon Neptune, ArangoDB, JanusGraph, TigerGraph.
Por que não é só uma tabela de junções
Num banco relacional, "amigos dos amigos dos amigos" vira três auto-junções, e o custo cresce exponencialmente com a profundidade. Num banco de grafo, cada nó guarda ponteiros diretos para seus vizinhos — a travessia é proporcional ao subgrafo visitado, não ao tamanho da base.
É a diferença entre uma consulta que degrada com o crescimento da tabela e uma que degrada com o número de conexões percorridas.
Onde é a escolha certa
| Domínio | Consulta típica |
|---|---|
| Rede social | Amigos em comum, sugestão de conexão |
| Detecção de fraude | Contas ligadas por dispositivo, endereço ou cartão |
| Recomendação | "Quem comprou isso também comprou" |
| Grafo de conhecimento | Relações entre entidades |
| Rede / dependências | Impacto de uma falha, caminho crítico |
| Controle de acesso | Permissão herdada por hierarquia |
Trade-offs
Grafos ganham dramaticamente em travessia profunda e perdem em quase todo o resto:
- Agregação em massa ("total de vendas por mês") é mais lenta que em qualquer banco relacional ou colunar
- Escala horizontal é difícil — particionar um grafo é um problema em aberto, porque qualquer corte separa arestas que serão percorridas
- Ecossistema menor, menos gente com experiência
- Linguagem própria (Cypher, Gremlin, SPARQL), sem o padrão que o SQL oferece
O critério prático: se a profundidade das consultas é 1 ou 2 saltos, um banco relacional com bons índices resolve — e resolve melhor. O grafo compensa a partir de 3 saltos ou mais, ou quando a profundidade é variável e desconhecida de antemão.
Uma arquitetura comum evita a escolha binária: manter o dado no banco principal e projetar o subgrafo relevante num banco de grafo dedicado, usado apenas para as consultas de travessia.
Exemplo prático
Detecção de fraude: encontrar contas conectadas por qualquer caminho a uma conta comprovadamente fraudulenta.
MATCH (f:Conta {fraude: true})-[*1..4]-(suspeita:Conta)
RETURN DISTINCT suspeita
Uma consulta, profundidade variável de 1 a 4 saltos, atravessando dispositivos, endereços, cartões e transferências.
Em SQL, isso seria uma CTE recursiva sobre milhões de linhas, com desempenho que piora a cada nível — e um custo que torna a consulta inviável em tempo real. Aqui a travessia visita apenas o subgrafo conectado, que costuma ser pequeno mesmo numa base enorme.
Relacionado
Parte de Databases · roadmap.sh/system-design