Quando você está criando aplicativos, a linguagem de consulta com a qual você trabalha faz uma grande diferença. Ela afeta tudo, desde o desempenho até a rapidez com que sua equipe pode enviar recursos. Nesta publicação, pedi a um LLM que criasse uma lista de 21 critérios classificados como os mais valiosos para decidir qual linguagem de consulta usar. Examinaremos cada um deles e mostraremos como as linguagens SQL++, usada pelo Couchbase, e a Query API do Mongo (anteriormente conhecida como MQL) se comparam.
Se você estiver avaliando bancos de dados para um novo projeto ou apenas curioso sobre as diferenças entre essas duas abordagens, isso deve lhe dar uma visão clara de onde cada um se destaca e onde pode ficar aquém.
Expressividade
O SQL++ permite que você escreva consultas ricas e complexas - uniões, subconsultas, agregados, funções de janela - enquanto trabalha com dados de documentos flexíveis. É possível expressar quase tudo o que você esperaria de um SQL, além do suporte nativo a JSON.
A linguagem de consulta do Mongo é mais limitada. Você pode fazer muito com o pipeline de agregação, mas expressar junções de várias coleções ou subconsultas profundas pode se tornar prolixo e exigir soluções alternativas ou construções avançadas de pipeline.
| SQL++ | Mongo | ||||
|---|---|---|---|---|---|
|
O Mongo exige um pipeline mais processual:
|
Legibilidade
O SQL++ é declarativo e familiar a qualquer pessoa com experiência em SQL. A intenção da consulta é fácil de ver.
|
1 2 3 4 |
SELECT name, age FROM users WHERE age >= 21 ORDER BY name; |
O pipeline do Mongo é mais detalhado e processual - você precisa percorrer mentalmente cada estágio.
|
1 2 3 4 |
db.users.find( { age: { $gte: 21 } }, { name: 1, age: 1, _id: 0 } ).sort({ name: 1 }); |
Para consultas simples, isso não é terrível. Mas, à medida que as consultas aumentam (uniões, subconsultas, agregações), a legibilidade pode cair rapidamente no formato de pipeline do Mongo.
Consistência
O SQL++ é altamente consistente. A sintaxe e a semântica são previsíveis, e ele se parece com o "SQL para documentos" em todos os aspectos.
Exemplo com dados aninhados:
|
1 2 3 4 |
SELECT u.name, a.city FROM users u UNNEST u.addresses AS a WHERE a.country = "USA"; |
No Mongo, a consulta de estruturas aninhadas geralmente requer a mudança para notação de ponto ou operadores de matriz, e os pipelines usam um estilo diferente do find(). Você acaba aprendendo várias sintaxes:
Consulta simples com notação de ponto:
|
1 2 3 4 |
db.users.find( { "addresses.country": "USA" }, { name: 1, "addresses.city": 1, _id: 0 } ); |
Mais complexo? Você está de volta à terra da agregação:
|
1 2 3 4 5 |
db.users.aggregate([ { $unwind: "$addresses" }, { $match: { "addresses.country": "USA" } }, { $project: { name: 1, city: "$addresses.city", _id: 0 } } ]); |
Desempenho
Quando se trata de desempenho bruto, o Couchbase SQL++ supera consistentemente a linguagem de consulta do MongoDB em benchmarks, especialmente em cargas de trabalho de alta taxa de transferência e baixa latência.
O Couchbase demonstrou escalabilidade e eficiência superiores em vários benchmarks. Por exemplo, no Yahoo! Cloud Serving Benchmark (YCSB), o Couchbase exibiu desempenho significativamente melhor no aumento de escala em comparação com o MongoDB.
Além dos benchmarks, os clientes do Couchbase relataram melhorias significativas no desempenho:
-
- A FICO escolheu o Couchbase em vez do MongoDB para obter um tempo de resposta <1 ms
- O LinkedIn escolheu o Couchbase em vez do MongoDB para executar mais de 10 milhões de consultas por segundo
A versão mais recente do MongoDB, embora tenha melhorado em relação às versões anteriores, ainda está defasada em determinados cenários. O MongoDB 8.0 introduziu aprimoramentos de desempenho, alcançando cargas de trabalho mistas de leitura/gravação mais rápidas em comparação com o MongoDB 7.0. No entanto, essas melhorias são relativas ao seu próprio desempenho anterior e podem não corresponder à escalabilidade e à velocidade demonstradas pelo Couchbase em benchmarks independentes (como o Classificação do banco de dados BenchANT).
Suporte a índices
O SQL++ oferece suporte a um amplo conjunto de índices: primário, secundário, composto, matriz, parcial, cobertura, FTS - todos utilizáveis em um único idioma.
O Mongo é compatível com o sistema primário (em _id), secundário, composto, multichave, texto e índices com hash. Ele é robusto, mas não tem a flexibilidade do SQL++ quando se trata de indexar campos ou expressões profundamente aninhados.
Exemplo com índice parcial em SQL++:
|
1 2 |
CREATE INDEX idx_active_users ON users(email) WHERE active = TRUE; |
O índice parcial do Mongo é semelhante:
|
1 2 3 4 |
db.users.createIndex( { email: 1 }, { partialFilterExpression: { active: true } } ); |
Recursos de união
O SQL++ suporta a sintaxe JOIN completa - interna e externa esquerda, INÚTILe combinações. Ele trata os documentos como cidadãos de primeira classe em consultas de estilo relacional.
Exemplo:
|
1 2 3 4 |
SELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id WHERE o.total > 100; |
Mongo's $lookup suporta pipelines mais expressivos desde a versão 5.0, mas ainda é ESQUERDA EXTERIOR e não possui a sintaxe completa de junção.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
db.orders.aggregate([ { $match: { total: { $gt: 100 } } }, { $lookup: { from: "users", localField: "user_id", foreignField: "id", as: "user" } }, { $unwind: "$user" }, { $project: { name: "$user.name", total: 1 } } ]); |
O SQL++ também oferece suporte a várias uniões e uniões em expressões - o $lookup é mais limitado em comparação.
Suporte à agregação
O SQL++ tem funções GROUP BY, HAVING, funções de janela e expressões flexíveis completas - exatamente como o SQL padrão.
Exemplo:
|
1 2 3 4 |
SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department HAVING avg_salary > 75000; |
O pipeline de agregação do Mongo é capaz, mas mais processual. Você encadeia estágios como $group, $match, Projeto $etc:
|
1 2 3 4 |
db.employees.aggregate([ { $group: { _id: "$department", avg_salary: { $avg: "$salary" } } }, { $match: { avg_salary: { $gt: 75000 } } } ]); |
Ambos são avançados, mas o SQL++ é normalmente mais conciso e familiar para os usuários de SQL e oferece suporte a recursos como funções da janela que o pipeline do Mongo não possui.
Filtragem e lógica de predicados
O SQL++ tem suporte total para filtragem complexa com E, OU, NÃO, ENTRE, INsubconsultas e expressões arbitrárias.
Exemplo:
|
1 2 3 4 5 |
SELECT name FROM users WHERE (age BETWEEN 21 AND 65) AND (email LIKE "%@example.com") AND (status IN ["active", "pending"]); |
O Mongo oferece suporte à filtragem em find() e em $match mas a sintaxe é mais detalhada e baseada em JSON:
|
1 2 3 4 5 |
db.users.find({ age: { $gte: 21, $lte: 65 }, email: { $regex: "@example\\.com$" }, status: { $in: ["active", "pending"] } }); |
Ambos podem expressar predicados complexos, mas o SQL++ tende a ser mais legível para lógica booleana altamente complexa.
Suporte a subconsultas
O SQL++ oferece suporte a subconsultas completas: correlacionadas, não correlacionadas e escalares, EXISTE/NÃO EXISTE-Todos os padrões que você espera.
Exemplo:
|
1 2 3 4 5 6 |
SELECT name FROM users u WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.user_id = u.id AND o.total > 100 ); |
O Mongo não oferece suporte a subconsultas da mesma forma. Geralmente, é necessário reescrever usando $lookup, $facetou várias consultas no código do aplicativo. Essa é uma área em que o SQL++ é muito mais forte e mais natural.
Suporte à manipulação de dados
O SQL++ oferece suporte a INSERIR, ATUALIZAÇÃO, DELETE, MERGE - todas as operações padrão de manipulação de dados.
Exemplo ATUALIZAÇÃO:
|
1 2 3 |
UPDATE users SET status = "inactive" WHERE last_login < "2024-01-01"; |
O Mongo também oferece suporte à manipulação de dados por meio de insertOne, insertMany, updateOne, updateMany, deleteOne, deleteManye replaceOne. A funcionalidade é sólida, mas as operações são chamadas de API separadas, não unificadas em uma linguagem de consulta.
Exemplo de atualização:
|
1 2 3 4 |
db.users.updateMany( { last_login: { $lt: new Date("2024-01-01") } }, { $set: { status: "inactive" } } ); |
Ambos são capazes, mas o SQL++ oferece uma linguagem única e consistente para consulta e modificação de dados.
Suporte a transações
O SQL++ oferece suporte a transações ACID de várias declarações (com o INICIAR TRANSAÇÃO, COMPROMISSO, ROLLBACK), e as transações podem abranger vários documentos, coleções e até mesmo vários extratos.
Exemplo:
|
1 2 3 4 |
BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = "user123"; UPDATE accounts SET balance = balance + 100 WHERE id = "user456"; COMMIT; |
O Mongo introduziu transações ACID de vários documentos na versão 4.0. Elas são suportadas, mas devem ser iniciadas a partir de drivers usando um objeto de sessão, ou mongosh, que não faz parte da própria linguagem de consulta do Mongo.
Exemplo (baseado em driver no Node.js):
|
1 2 3 4 5 6 7 8 9 10 |
const session = client.startSession(); session.startTransaction(); try { db.accounts.updateOne({ id: "user123" }, { $inc: { balance: -100 } }, { session }); db.accounts.updateOne({ id: "user456" }, { $inc: { balance: 100 } }, { session }); await session.commitTransaction(); } catch (error) { await session.abortTransaction(); } session.endSession(); |
Resumo: ambos oferecem suporte a transações ACID, mas o SQL++ permite que você as expresse de forma declarativa dentro da própria linguagem de consulta, o que é mais fácil e mais claro.
Tratamento de erros
O SQL++ apresenta códigos de erro estruturados e mensagens para o cliente quando uma consulta falha - eles podem ser acessados por meio dos SDKs e dos metadados da consulta. Você também pode escrever consultas de forma defensiva (por exemplo, IF EXISTS, IF MISSING, expressões CASE) para controlar o comportamento.
Exemplo (lógica defensiva):
|
1 2 3 4 |
UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = "user123" AND last_login IS NOT MISSING; |
Os códigos de erro estão documentados aqui: Códigos de erro do Couchbase SQL++.
O Mongo também se baseia no tratamento de erros em nível de driver - os erros são enviados ao cliente quando as consultas ou os comandos falham. O pipeline de agregação do Mongo também não oferece suporte ao tratamento de erros na consulta.
Exemplo (atualização defensiva do Mongo):
|
1 2 3 4 |
db.users.updateOne( { user_id: "user123", last_login: { $exists: true } }, { $set: { last_login: new Date() } } ); |
Resumo: tanto o SQL++ quanto o Mongo dependem do tratamento de erros externos (em nível de driver). Você pode usar padrões de consulta defensivos para atenuar erros comuns.
Extensibilidade
O SQL++ permite funções definidas pelo usuário (UDFs) escritas no próprio SQL++. Elas podem encapsular lógicas complexas, reutilizar expressões e simplificar as consultas.
Exemplo de UDF:
|
1 2 3 4 5 6 7 |
CREATE FUNCTION get_discount(total FLOAT) RETURNS FLOAT AS CASE WHEN total > 500 THEN 0.10 WHEN total > 100 THEN 0.05 ELSE 0.0 END; |
Uso:
|
1 2 |
SELECT customer_id, total, get_discount(total) AS discount FROM orders; |
O Mongo não tem UDFs de consulta em sua linguagem de consulta ou pipeline de agregação. Você pode usar $função (introduzido no MongoDB 4.4), que permite que você execute funções JavaScript dentro da agregação, mas isso é menos eficiente e limitado em termos de portabilidade:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
db.orders.aggregate([ { $addFields: { discount: { $function: { body: function(total) { if (total > 500) return 0.10; if (total > 100) return 0.05; return 0.0; }, args: ["$total"], lang: "js" } } } } ]); |
Resumo: os UDFs do SQL++ são nativos, eficientes e portáteis; os UDFs do Mongo $função usa JavaScript e pode ter desvantagens de desempenho.
Natureza declarativa
O SQL++ é totalmente declarativo - você expressa o que deseja, não como calcular. Você conta com o otimizador de consultas para determinar o melhor plano de execução. Isso torna as consultas mais simples de escrever e manter.
O pipeline de agregação do Mongo é mais processual - você especifica a sequência exata de operações ($match, $group, Projeto $, $sortetc.). No caso de lógica complexa, isso geralmente requer pensar em termos de fluxo de dados, não de resultado desejado.
Portabilidade
O SQL++ é baseado em SQL com extensões JSON. Se você conhece SQL, é fácil aprender SQL++, e grande parte do seu conhecimento é transferido. A linguagem também foi projetada para ser portável em todas as implantações do Couchbase - nuvem, autogerenciada, borda.
A linguagem de consulta do Mongo é específica do MongoDB. Sua sintaxe é baseada em JSON, não em SQL, e a maior parte dela não é transferida para outros bancos de dados. Embora seja ótima dentro do ecossistema Mongo, é mais difícil de ser transferida para sistemas como bancos de dados relacionais, Couchbase ou data warehouses em nuvem.
Suporte à paginação
O SQL++ oferece suporte à paginação usando LIMITE e DESLOCAMENTO - estilo SQL padrão:
|
1 2 3 4 |
SELECT name FROM users ORDER BY name LIMIT 10 OFFSET 20; |
O Mongo também oferece suporte à paginação com .limit() e .skip():
|
1 2 3 4 |
db.users.find({}) .sort({ name: 1 }) .skip(20) .limit(10); |
Ambos lidam bem com a paginação básica.
No entanto, o SQL++ também oferece suporte a funções de janela (por exemplo ROW_NUMBER() OVER (...)), que permite padrões mais avançados de paginação e baseados em cursor, enquanto o Mongo requer estágios adicionais de pipeline ou lógica de aplicativo para simulá-los.
Introspecção de esquema
O SQL++ / Couchbase oferece suporte à descoberta automática de esquemas por meio do INFER comando. Como o Couchbase é flexível em termos de esquema, INFER permite analisar documentos em uma coleção e gerar um esquema probabilístico, mostrando quais campos existem, seus tipos, aninhamento e porcentagens de ocorrência.
Exemplo:
|
1 |
INFER `travel-sample`.inventory.airline WITH { "sample_size": 1000 }; |
Retorna informações sobre a coleção de linhas aéreas, incluindo nomes de campos, tipos e porcentagens de ocorrência:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[ [ { "#docs": 187, "$schema": "https://json-schema.org/draft-06/schema", "Flavor": "`type` = \"airline\"", "properties": { "callsign": { ... }, "country": { ... }, "name": { ... }, ... }, "type": "object" } ] ] |
O Mongo não tem uma linguagem de consulta direta equivalente a INFERembora o MongoDB Atlas ofereça o Schema Explorer na interface do usuário.
Opções mais próximas:
-
- db.collection.aggregate([ { $sample: { size: N } } ]) + inspeção manual
- Ferramentas de terceiros
Suporte a ferramentas e IDE
O SQL++ é compatível com:
-
- Workbench de consulta da interface do usuário da Web do Couchbase
- Extensão SQL++ do VS Code
- IDEs da JetBrains (plug-in)
- API REST / CLI
- Shell do Couchbase
As ferramentas do Mongo incluem:
-
- MongoDB Compass (GUI)
- Mongo Shell / mongosh
- IU do MongoDB Atlas
- Código VS Extensão do MongoDB
Há outras ferramentas também. Ambos têm boas ferramentas. O SQL++ se integra melhor com ferramentas compatíveis com SQL (DataGrip, ferramentas de BI, etc.). As ferramentas do Mongo são mais específicas para o Mongo.
Comunidade e documentação
SQL++ / Couchbase:
-
- Documentos oficiais: Referência do Couchbase SQL++
- Comunidade ativa de desenvolvedores do Couchbase
- Blogs, fóruns, Stack Overflow, Discord
- O SQL++ é baseado no SQL conhecido, portanto, os recursos SQL existentes também se aplicam
Mongo:
-
- Documentos oficiais: Referência da linguagem de consulta do MongoDB
- Grande comunidade
- Muitos tutoriais, cursos e livros
- Muito usado em comunidades de desenvolvimento web / JavaScript
O Mongo tem uma comunidade maior (simplesmente devido à adoção mais ampla), mas o SQL++ se beneficia da familiaridade com o SQL e de um ecossistema de desenvolvedores do Couchbase cada vez mais ativo.
Integração com estruturas de aplicativos
O SQL++ / Couchbase é suportado via:
-
- SDKs nas principais linguagens: Java, .NET (C#), Node.js, Python, Go, C++, Scala
- Drivers ODBC / JDBC → funciona com ferramentas de BI (Tableau, Power BI, Excel, Looker)
- API REST
- Um ecossistema crescente de integraçõesincluindo Spring Data, EF Core, Quarkus e muito mais
O Mongo tem:
-
- Drivers oficiais para quase todos os principais idiomas
- Ecossistema sólido para desenvolvedores
O Mongo tem um ecossistema maior, mas o SQL++ é mais familiar para os desenvolvedores de SQL em geral.
Conformidade com os padrões
O SQL++ é uma linguagem derivada do SQL:
-
- Baseado em ANSI SQL com extensões para documentos JSON, matrizes, aninhamento
- Você pode usar as habilidades padrão de SQL e usá-las imediatamente
- Muitas ferramentas e padrões baseados em SQL existentes se aplicam
A linguagem de consulta do Mongo não é padrão:
-
- Com base na sintaxe e nos operadores JSON
- Nenhum mapeamento direto para ANSI SQL
- Requer o aprendizado de padrões de consulta específicos do Mongo
Se você quiser compatibilidade com SQL e alinhamento de padrões, procure o SQL++. Se você não tiver problemas com uma linguagem específica do Mongo, a abordagem do Mongo funciona, mas é mais difícil de portar.
Resumo
O SQL++ é uma opção natural para desenvolvedores familiarizados com SQL. É um superconjunto do SQL, portanto, o conhecimento existente sobre SQL é transferido.
A linguagem de consulta do MongoDB é mais especializada e processual, o que pode ser poderoso, mas também exige uma mentalidade diferente.
Aqui está a lista completa de critérios:
| Classificação | Nome do critério | Como aplicar | Por que é importante |
| 1 | Expressividade | Avaliar quantos tipos de consultas podem ser escritos | Determina a flexibilidade no tratamento de tarefas de dados |
| 2 | Legibilidade | Revisar exemplos de consultas para maior clareza | Impacta a curva de aprendizado e a manutenção |
| 3 | Consistência | Procure sintaxe e semântica consistentes | Reduz bugs e surpresas |
| 4 | Desempenho | Execução de consultas de benchmark em cargas de trabalho reais | Afeta a velocidade e a escalabilidade |
| 5 | Suporte a índices | Verificar a variedade de tipos de índices e opções de uso | Essencial para otimizar a velocidade de consulta |
| 6 | Recursos de união | Suporte de teste para diferentes tipos de união | Chave para trabalhar com dados relacionados |
| 7 | Suporte à agregação | Avaliar o suporte para agrupamento e agregação | Necessário para análises e relatórios |
| 8 | Filtragem e lógica de predicados | Testar cláusulas WHERE e HAVING complexas | Permite a recuperação precisa de dados |
| 9 | Suporte a subconsultas | Verificar o suporte a subconsultas correlacionadas e aninhadas | Adiciona profundidade à consulta |
| 10 | Suporte à manipulação de dados | Teste a funcionalidade INSERT, UPDATE, DELETE e MERGE | Importante para a manutenção de dados |
| 11 | Suporte a transações | Suporte de verificação para transações com vários extratos | Garante a consistência e a atomicidade dos dados |
| 12 | Tratamento de erros | Revisar os mecanismos de detecção e comunicação de erros | Ajuda na depuração e na confiabilidade |
| 13 | Extensibilidade | Verificar a capacidade de adicionar funções definidas pelo usuário (UDFs) | Permite a personalização para necessidades avançadas |
| 14 | Natureza declarativa | Determinar se o idioma especifica o que para fazer, não como | Simplifica o desenvolvimento e a otimização |
| 15 | Portabilidade | Veja como as consultas migram facilmente entre sistemas | Reduz a dependência de fornecedores e ajuda na flexibilidade |
| 16 | Suporte à paginação | Teste o suporte a LIMIT, OFFSET ou janelamento | Crítico para APIs e acesso a dados orientado pela interface do usuário |
| 17 | Introspecção de esquema | Verificar a consulta de metadados de esquema/catálogo | Suporta automação e ferramentas |
| 18 | Suporte a ferramentas e IDE | Pesquisar o ecossistema de editores de consultas, plug-ins etc. | Impacta a produtividade do desenvolvedor |
| 19 | Comunidade e documentação | Revisar a qualidade dos documentos, fóruns da comunidade e tutoriais | Afeta a facilidade de aprendizado e solução de problemas |
| 20 | Integração com estruturas de aplicativos | Verifique o suporte a bibliotecas e drivers em idiomas populares | Facilita o desenvolvimento de aplicativos |
| 21 | Conformidade com os padrões | Comparar com os padrões do setor (por exemplo, SQL) | Ajuda na portabilidade e interoperabilidade |