Cuando se crean aplicaciones, el lenguaje de consulta con el que se trabaja marca una gran diferencia. Afecta a todo, desde el rendimiento hasta la rapidez con la que tu equipo puede enviar funcionalidades. En este post, he pedido a un LLM que cree una lista de los 21 criterios más valiosos a la hora de decidir qué lenguaje de consulta utilizar. Repasaremos cada uno de ellos y mostraremos cómo se comparan los lenguajes SQL++, utilizado por Couchbase, y el Query API de Mongo (anteriormente conocido como MQL).
Tanto si está evaluando bases de datos para un nuevo proyecto como si simplemente siente curiosidad por conocer las diferencias entre estos dos enfoques, esto le dará una idea clara de dónde brilla cada uno y dónde puede quedarse corto.
Expresividad
SQL++ le permite escribir consultas ricas y complejas -uniones, subconsultas, agregados, funciones de ventana- mientras trabaja con datos de documentos flexibles. Puede expresar casi cualquier cosa que esperaría en SQL, además de soporte nativo para JSON.
El lenguaje de consulta de Mongo es más limitado. Se pueden hacer muchas cosas con la canalización de agregación, pero expresar uniones multicolección o subconsultas profundas puede volverse farragoso y requerir soluciones o construcciones de canalización avanzadas.
SQL | Mongo | ||||
---|---|---|---|---|---|
|
Mongo requiere un proceso más procedimentado:
|
Legibilidad
SQL++ es declarativo y familiar para cualquiera con experiencia en SQL. La intención de la consulta es fácil de ver.
1 2 3 4 |
SELECCIONE nombre, edad DESDE usuarios DONDE edad >= 21 PEDIR POR nombre; |
El proceso de Mongo es más prolijo y procedimental: hay que recorrer mentalmente cada etapa.
1 2 3 4 |
db.usuarios.encontrar( { edad: { $gte: 21 } }, { nombre: 1, edad: 1, _id: 0 } ).ordenar({ nombre: 1 }); |
Para consultas sencillas esto no es terrible. Pero a medida que crecen las consultas (uniones, subconsultas, agregaciones), la legibilidad puede caer rápidamente en el formato de canalización de Mongo.
Coherencia
SQL++ es muy coherente. La sintaxis y la semántica son predecibles y, en general, parece "SQL para documentos".
Ejemplo con datos anidados:
1 2 3 4 |
SELECCIONE u.nombre, a.ciudad DESDE usuarios u UNNEST u.direcciones AS a DONDE a.país = "USA"; |
En Mongo, la consulta de estructuras anidadas a menudo requiere cambiar a la notación por puntos o a operadores de matrices, y las canalizaciones utilizan un estilo diferente al de encontrar(). Acabas aprendiendo múltiples sintaxis:
Consulta simple con notación por puntos:
1 2 3 4 |
db.usuarios.encontrar( { "direcciones.pais": "USA" }, { nombre: 1, "direcciones.ciudad": 1, _id: 0 } ); |
¿Más complejo? Estás de vuelta en la tierra de la agregación:
1 2 3 4 5 |
db.usuarios.agregado([ { $desenrollar: "1TP4Direcciones" }, { $match: { "direcciones.pais": "USA" } }, { $proyecto: { nombre: 1, ciudad: "1TP4Direcciones.ciudad", _id: 0 } } ]); |
Rendimiento
Cuando se trata de rendimiento bruto, Couchbase SQL++ supera consistentemente al lenguaje de consulta de MongoDB en los benchmarks, especialmente bajo cargas de trabajo de alto rendimiento y baja latencia.
Couchbase ha demostrado una escalabilidad y eficiencia superiores en varias pruebas comparativas. Por ejemplo, en el Yahoo! Cloud Serving Benchmark (YCSB), Couchbase exhibió rendimiento significativamente mejor a escala en comparación con MongoDB.
Más allá de las pruebas comparativas, los clientes de Couchbase han informado de mejoras significativas en el rendimiento:
-
- FICO eligió Couchbase en lugar de MongoDB para lograr un tiempo de respuesta <1ms
- LinkedIn eligió Couchbase en lugar de MongoDB ejecutar más de 10 millones de consultas por segundo
La última versión de MongoDB, aunque ha mejorado con respecto a sus versiones anteriores, todavía se queda atrás en ciertos escenarios. MongoDB 8.0 introdujo mejoras de rendimiento, consiguiendo cargas de trabajo mixtas de lectura/escritura más rápidas en comparación con MongoDB 7.0. Sin embargo, estas mejoras son relativas a su propio rendimiento anterior y puede que no alcancen la escalabilidad y velocidad demostradas por Couchbase en pruebas comparativas independientes (como la de Clasificación de la base de datos BenchANT).
Ayuda al índice
SQL++ admite un amplio conjunto de índices: primario, secundario, compuesto, matriz, parcial, cobertura, FTS-todos utilizables desde un único lenguaje.
Mongo admite primary (en _id), índices secundarios, compuestos, multiclave, de texto y hash. Es potente, pero carece de parte de la flexibilidad de SQL++ cuando se trata de indexar campos o expresiones profundamente anidados.
Ejemplo con índice parcial en SQL++:
1 2 |
CREAR ÍNDICE idx_usuarios_activos EN usuarios(correo electrónico) DONDE activo = TRUE; |
El índice parcial de Mongo es similar:
1 2 3 4 |
db.usuarios.createIndex( { correo electrónico: 1 }, { partialFilterExpression: { activo: verdadero } } ); |
Unir capacidades
SQL++ soporta la sintaxis completa de JOIN-inner, left outer, UNNESTy combinaciones. Trata los documentos como ciudadanos de primera clase en las consultas de tipo relacional.
Por ejemplo:
1 2 3 4 |
SELECCIONE u.nombre, o.total DESDE usuarios u ÚNASE A pedidos o EN u.id = o.usuario_id DONDE o.total > 100; |
Mongo's 1TP4Búsqueda soporta pipelines más expresivos desde 5.0, pero sigue siendo EXTERIOR IZQUIERDA y carece de sintaxis de unión completa.
1 2 3 4 5 6 7 8 9 10 11 12 |
db.pedidos.agregado([ { $match: { total: { $gt: 100 } } }, { $buscar: { de: "usuarios", localField: "user_id", foreignField: "id", como: "usuario" } }, { $desenrollar: "$user" }, { $proyecto: { nombre: "$user.name", total: 1 } } ]); |
SQL++ también admite uniones múltiples y uniones sobre expresiones. 1TP4Búsqueda es más limitado en comparación.
Soporte de agregación
SQL++ dispone de funciones completas GROUP BY, HAVING, funciones de ventana y expresiones flexibles, al igual que SQL estándar.
Por ejemplo:
1 2 3 4 |
SELECCIONE departamento, AVG(salario) AS salario_avg DESDE empleados GRUPO POR departamento TENIENDO salario_avg > 75000; |
La tubería de agregación de Mongo es capaz, pero más procedimental. Se encadenan etapas como Grupo $, $match, Proyecto $etc:
1 2 3 4 |
db.empleados.agregado([ { $grupo: { _id: "$departamento", salario_avg: { $media: "$salario" } } }, { $match: { salario_avg: { $gt: 75000 } } } ]); |
Ambos son potentes, pero SQL++ suele ser más conciso y familiar para los usuarios de SQL, y admite funciones como funciones de ventana que le falta a la tubería de Mongo.
Filtrado y lógica de predicados
SQL++ es totalmente compatible con el filtrado complejo con Y, O, NO, ENTRE, ENsubconsultas y expresiones arbitrarias.
Por ejemplo:
1 2 3 4 5 |
SELECCIONE nombre DESDE usuarios DONDE (edad ENTRE 21 Y 65) Y (correo electrónico COMO "%@example.com") Y (estado EN ["activo", "pendiente"]); |
Mongo admite el filtrado en encontrar() y en $match pero la sintaxis es más verbosa y basada en JSON:
1 2 3 4 5 |
db.usuarios.encontrar({ edad: { $gte: 21, $lte: 65 }, correo electrónico: { $regex: "@ejemplo\\.com$" }, estado: { $en: ["activo", "pendiente"] } }); |
Ambos pueden expresar predicados complejos, pero SQL++ tiende a ser más legible para la lógica booleana de gran complejidad.
Soporte de subconsultas
SQL++ admite subconsultas completas: correlacionadas, no correlacionadas, escalares, EXISTE/NO EXISTE-todos los patrones que cabría esperar.
Por ejemplo:
1 2 3 4 5 6 |
SELECCIONE nombre DESDE usuarios u DONDE EXISTE ( SELECCIONE 1 DESDE pedidos o DONDE o.usuario_id = u.id Y o.total > 100 ); |
Mongo no soporta subconsultas de la misma manera. Generalmente hay que reescribir usando 1TP4Búsqueda, $faceto múltiples consultas en el código de la aplicación. Esta es un área en la que SQL++ es mucho más fuerte y natural.
Manipulación de datos
SQL++ admite INSERTAR, ACTUALIZACIÓN, BORRAR, FUSIONAR - todas las operaciones estándar de manipulación de datos.
Ejemplo ACTUALIZACIÓN:
1 2 3 |
ACTUALIZACIÓN usuarios SET estado = "inactivo" DONDE último_ingreso < "2024-01-01"; |
Mongo también admite la manipulación de datos mediante insertarUno, insertMany, updateUno, updateMany, deleteOne, deleteManyy replaceOne. La funcionalidad es sólida, pero las operaciones son llamadas API separadas, no unificadas en un lenguaje de consulta.
Ejemplo de actualización:
1 2 3 4 |
db.usuarios.updateMany( { último_ingreso: { $lt: nuevo Fecha("2024-01-01") } }, { $configure: { estado: "inactivo" } } ); |
Ambos son capaces, pero SQL++ proporciona un lenguaje único y coherente tanto para la consulta como para la modificación de datos.
Apoyo a las transacciones
SQL++ admite transacciones ACID multiestado (con la tecnología INICIAR TRANSACCIÓN, COMPROMETERSE, ROLLBACK), y las transacciones pueden abarcar varios documentos, colecciones e incluso varios extractos.
Por ejemplo:
1 2 3 4 |
COMENZAR TRANSACCIÓN; ACTUALIZACIÓN cuentas SET saldo = saldo - 100 DONDE id = "user123"; ACTUALIZACIÓN cuentas SET saldo = saldo + 100 DONDE id = "user456"; COMPROMETERSE; |
Mongo introdujo las transacciones ACID multi-documento en la versión 4.0. Están soportadas, pero deben ser iniciadas desde controladores usando un objeto de sesión, o mongosh, no parte del lenguaje de consulta de Mongo en sí.
Ejemplo (basado en controlador en Node.js):
1 2 3 4 5 6 7 8 9 10 |
const sesión = cliente.startSession(); sesión.startTransaction(); pruebe { db.cuentas.updateUno({ id: "user123" }, { $inc: { saldo: -100 } }, { sesión }); db.cuentas.updateUno({ id: "user456" }, { $inc: { saldo: 100 } }, { sesión }); await sesión.commitTransaction(); } captura (error) { await sesión.abortTransaction(); } sesión.endSession(); |
Resumen: Ambos soportan transacciones ACID, pero SQL++ permite expresarlas de forma declarativa dentro del propio lenguaje de consulta, lo que resulta más sencillo y claro.
Tratamiento de errores
SQL++ muestra códigos de error estructurados y mensajes al cliente cuando una consulta falla - estos son accesibles a través de los SDKs y los metadatos de consulta. También puede escribir consultas de forma defensiva (por ejemplo, expresiones IF EXISTS, IF MISSING, CASE) para controlar el comportamiento.
Ejemplo (lógica defensiva):
1 2 3 4 |
ACTUALIZACIÓN usuarios SET último_ingreso = HORA_ACTUAL DONDE usuario_id = "user123" Y último_ingreso IS NO FALTA; |
Los códigos de error se documentan aquí: Códigos de error SQL++ de Couchbase.
Mongo también se basa en la gestión de errores a nivel de controlador: los errores se envían al cliente cuando fallan las consultas o los comandos. El canal de agregación de Mongo tampoco admite la gestión de errores en la consulta.
Ejemplo (actualización defensiva de Mongo):
1 2 3 4 |
db.usuarios.updateUno( { usuario_id: "user123", último_ingreso: { $existe: verdadero } }, { $configure: { último_ingreso: nuevo Fecha() } } ); |
Resumen: Tanto SQL++ como Mongo se basan en el manejo de errores externos (a nivel de controlador). Puedes usar patrones de consulta defensivos para mitigar errores comunes.
Extensibilidad
SQL++ permite funciones definidas por el usuario (UDF) escritas en el propio SQL++. Estas pueden encapsular lógica compleja, reutilizar expresiones y simplificar las consultas.
Ejemplo de UDF:
1 2 3 4 5 6 7 |
CREAR FUNCIÓN obtener_descuento(total FLOTADOR) DEVOLUCIONES FLOTADOR AS CASO CUANDO total > 500 ENTONCES 0.10 CUANDO total > 100 ENTONCES 0.05 ELSE 0.0 FIN; |
Uso:
1 2 |
SELECCIONE customer_id, total, obtener_descuento(total) AS descuento DESDE pedidos; |
Mongo no dispone de UDFs en su lenguaje de consulta ni en su canal de agregación. Puede utilizar 1TP4Función (introducido en MongoDB 4.4), que permite ejecutar funciones JavaScript dentro de la agregación - pero esto es menos eficiente y limitado en portabilidad:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
db.pedidos.agregado([ { $addFields: { descuento: { $función: { cuerpo: función(total) { si (total > 500) devolver 0.10; si (total > 100) devolver 0.05; devolver 0.0; }, args: ["$total"], lang: "js" } } } } ]); |
Resumen: Las UDF de SQL++ son nativas, eficientes y portables; las de Mongo 1TP4Función utiliza JavaScript y puede tener problemas de rendimiento.
Naturaleza declarativa
SQL++ es totalmente declarativo: usted expresa lo que desea, no cómo calcularlo. Usted confía en el optimizador de consultas para determinar el mejor plan de ejecución. Esto hace que las consultas sean más sencillas de escribir y mantener.
El proceso de agregación de Mongo es más procedimental: se especifica la secuencia exacta de operaciones ($match, Grupo $, Proyecto $, $sortetc.). En el caso de la lógica compleja, a menudo es necesario pensar en términos de flujo de datos, no de resultado deseado.
Portabilidad
SQL++ se basa en SQL con extensiones JSON. Si sabes SQL, es fácil aprender SQL++, y gran parte de tu conocimiento se traslada. El lenguaje también está diseñado para ser portable a través de los despliegues de Couchbase - nube, autogestionado, borde.
El lenguaje de consulta de Mongo es específico de MongoDB. Su sintaxis está basada en JSON, no en SQL, y la mayor parte no se transfiere a otras bases de datos. Aunque es genial dentro del ecosistema Mongo, es más difícil de portar a sistemas como bases de datos relacionales, Couchbase o almacenes de datos en la nube.
Soporte de paginación
SQL++ admite la paginación mediante LÍMITE y OFFSET - estilo SQL estándar:
1 2 3 4 |
SELECCIONE nombre DESDE usuarios PEDIR POR nombre LÍMITE 10 OFFSET 20; |
Mongo también admite la paginación con .limit() y .skip():
1 2 3 4 |
db.usuarios.encontrar({}) .ordenar({ nombre: 1 }) .omitir(20) .límite(10); |
Ambos manejan bien la paginación básica.
Sin embargo - SQL++ también soporta funciones de ventana (p.ej. NÚMERO_FILAS() SOBRE (...)), que permite una paginación más avanzada y patrones basados en cursor, mientras que Mongo requiere etapas adicionales de canalización o lógica de aplicación para simularlas.
Introspección de esquemas
SQL++ / Couchbase admite el descubrimiento automático de esquemas a través de la función INFER comando. Dado que Couchbase es flexible en cuanto a esquemas, INFER le permite analizar los documentos de una colección y generar un esquema probabilístico, mostrando qué campos existen, sus tipos, anidamiento y porcentajes de aparición.
Por ejemplo:
1 |
INFER `viaje-muestra`.inventario.aerolínea CON { "tamaño_muestra": 1000 }; |
Devuelve información sobre la colección de líneas aéreas, incluidos los nombres de los campos, los tipos y los porcentajes de aparición:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[ [ { "#docs": 187, "$schema": "http://json-schema.org/draft-06/schema", "Sabor": "`type` = \"airline\"", "propiedades": { "Indicativo": { ... }, "país": { ... }, "nombre": { ... }, ... }, "tipo": "objeto" } ] ] |
Mongo no tiene un lenguaje de consulta directo equivalente a INFERaunque MongoDB Atlas ofrece Schema Explorer en la interfaz de usuario.
Opciones más cercanas:
-
- db.collection.aggregate([ { $sample: { size: N } } ]) + inspección manual
- Herramientas de terceros
Herramientas y soporte IDE
SQL++ es compatible con:
-
- Interfaz web de Couchbase: Query Workbench
- Extensión SQL++ de VS Code
- JetBrains IDEs (complemento)
- API REST / CLI
- Shell de Couchbase
Las herramientas de Mongo incluyen:
-
- MongoDB Compass (GUI)
- Mongo Shell / mongosh
- Interfaz de usuario de MongoDB Atlas
- VS Code Extensión MongoDB
También hay otras herramientas. Ambas tienen buenas herramientas. SQL++ se integra mejor con herramientas SQL-friendly (DataGrip, herramientas BI, etc.). Las herramientas de Mongo son más específicas de Mongo.
Comunidad y documentación
SQL++ / Couchbase:
-
- Documentos oficiales: Referencia SQL++ de Couchbase
- Comunidad activa de desarrolladores de Couchbase
- Blogs, foros, Stack Overflow, Discord
- SQL++ se basa en el SQL conocido, por lo que los recursos SQL existentes también se aplican
Mongo:
-
- Documentación oficial: Referencia del lenguaje de consulta de MongoDB
- Gran comunidad
- Muchos tutoriales, cursos, libros
- Muy utilizado en las comunidades de desarrollo web y JavaScript
Mongo tiene una comunidad más grande (simplemente debido a una adopción más amplia), pero SQL++ se beneficia de la familiaridad con SQL y de un ecosistema de desarrolladores de Couchbase cada vez más activo.
Integración con App Frameworks
SQL++ / Couchbase es compatible a través de:
-
- SDKs en los principales lenguajes: Java, .NET (C#), Node.js, Python, Go, C++, Scala
- Controladores ODBC / JDBC → funciona con herramientas de BI (Tableau, Power BI, Excel, Looker).
- API REST
- Un creciente ecosistema de integracionescomo Spring Data, EF Core, Quarkus, etc.
Mongo sí:
-
- Controladores oficiales para casi todas las lenguas principales
- Sólido ecosistema para desarrolladores
Mongo tiene un ecosistema más amplio, pero SQL++ es más familiar para los desarrolladores de SQL en general.
Cumplimiento de las normas
SQL++ es un lenguaje derivado de SQL:
-
- Basado en ANSI SQL con extensiones para documentos JSON, matrices y anidamiento.
- Puede adquirir conocimientos estándar de SQL y utilizarlos de inmediato
- Muchas herramientas y modelos basados en SQL se aplican
El lenguaje de consulta de Mongo no es estándar:
-
- Basado en la sintaxis y los operadores JSON
- No hay correspondencia directa con ANSI SQL
- Requiere aprender patrones de consulta específicos de Mongo
Si quieres compatibilidad SQL y alineación con los estándares, busca SQL++. Si prefieres un lenguaje específico de Mongo, el enfoque de Mongo funciona, pero es más difícil de portar.
Resumen
SQL++ se adapta de forma natural a los desarrolladores familiarizados con SQL. Es un superconjunto de SQL, por lo que los conocimientos de SQL ya existentes se trasladan.
El lenguaje de consulta de MongoDB es más especializado y procedimental, lo que puede ser potente pero también requiere una mentalidad diferente.
Aquí está la lista completa de criterios:
Rango | Nombre de los criterios | Cómo aplicarlo | Por qué es importante |
1 | Expresividad | Evaluar cuántos tipos de consultas se pueden escribir | Determina la flexibilidad en el manejo de las tareas de datos |
2 | Legibilidad | Revisar ejemplos de consultas para mayor claridad | Impacto en la curva de aprendizaje y el mantenimiento |
3 | Coherencia | Sintaxis y semántica coherentes | Reduce errores y sorpresas |
4 | Rendimiento | Pruebas comparativas de ejecución de consultas en cargas de trabajo reales | Afecta a la velocidad y la escalabilidad |
5 | Ayuda al índice | Compruebe la gama de tipos de índice y las opciones de uso | Fundamental para optimizar la velocidad de consulta |
6 | Unir capacidades | Prueba de compatibilidad con distintos tipos de uniones | Clave para trabajar con datos relacionados |
7 | Soporte de agregación | Evaluar la compatibilidad con la agrupación y la agregación | Necesario para análisis e informes |
8 | Filtrado y lógica de predicados | Prueba de cláusulas WHERE y HAVING complejas | Permite recuperar datos con precisión |
9 | Soporte de subconsultas | Verificación de la compatibilidad con subconsultas correlacionadas y anidadas | Añade profundidad a las consultas |
10 | Manipulación de datos | Pruebe la funcionalidad INSERT, UPDATE, DELETE, MERGE | Importante para el mantenimiento de datos |
11 | Apoyo a las transacciones | Comprobación de transacciones con varios extractos | Garantiza la coherencia y atomicidad de los datos |
12 | Tratamiento de errores | Revisar los mecanismos de detección y notificación de errores | Ayuda a la depuración y la fiabilidad |
13 | Extensibilidad | Comprobar la capacidad de añadir funciones definidas por el usuario (UDF) | Permite la personalización para necesidades avanzadas |
14 | Naturaleza declarativa | Determine si la lengua especifica qué hacer, no cómo | Simplifica el desarrollo y la optimización |
15 | Portabilidad | Compruebe la facilidad con la que las consultas migran de un sistema a otro | Reduce la dependencia del proveedor y aumenta la flexibilidad |
16 | Soporte de paginación | Prueba de LÍMITE, OFFSET o soporte de ventanas | Fundamental para las API y el acceso a datos basado en la interfaz de usuario. |
17 | Introspección de esquemas | Comprobación de la consulta de metadatos de esquemas/catálogos | Apoya la automatización y el utillaje |
18 | Herramientas y soporte IDE | Estudio del ecosistema de editores de consultas, plugins, etc. | Impacto en la productividad de los desarrolladores |
19 | Comunidad y documentación | Revisar la calidad de los documentos, foros comunitarios y tutoriales | Afecta a la facilidad de aprendizaje y resolución de problemas |
20 | Integración con App Frameworks | Compruebe la compatibilidad de las bibliotecas y los controladores en los idiomas más habituales | Facilita el desarrollo de aplicaciones |
21 | Cumplimiento de las normas | Comparación con las normas del sector (por ejemplo, SQL) | Ayuda a la portabilidad y la interoperabilidad |