Las aplicaciones empresariales tienen requisitos: tomar pedidos de clientes, entregar pedidos de clientes, realizar un seguimiento de los envíos, generar informes de inventario, informes empresariales de final de día/mes/trimestre, generar cuadros de mando empresariales y mucho más. Estos requisitos evolucionan lentamente. Se mantienen incluso cuando se elige un Base de datos NoSQL.
En las bases de datos NoSQL, los retos se abordan con multitud de tecnologías y soluciones. He aquí algunas de ellas:
- Copiar los datos con una clave diferente para facilitar los escaneos.
- Obtener todos los datos necesarios para la aplicación y, a continuación, generar informes
- Cargar los datos en bases de datos relacionales para generar el informe.
- Los productos ofrecen soluciones con vistas map-reduce, APIsetc.
- Por último, el propio SQL irrazonablemente eficaz tanto para datos estructurados como semiestructurados. Bases de datos NoSQL como Couchbase, Cassandra, CosmosDB han ampliado SQL para JSON y el modelo de datos de columnas anchas.
NoSQL ha evolucionado de "NO SQL" a No Sólo SQL. Si te interesan algunos de los antecedentes evolutivos combinados con una historia de la evolución de SQL para soportar datos semiestructurados, te sugiero las siguientes entrevistas.
- Entrevista de Ravi Mayuram con Don Chamberlin[2017]: https://youtu.be/-U_UjqnhMBI?t=3492
- Una mesa redonda entre Ravi Mayuram, Don Chamberlin y el profesor Mike Carey [2018]: https://www.youtube.com/watch?v=LAlDe1w7wxc
Muchas bases de datos NoSQL afirman ser "compatibles con SQL". El sitio Norma SQL es ancho y profundo, cubierto de nueve voluminosos libros. Nadie, ni Oracle ni Servidor SQLsoporta todo lo que contiene el estándar a pesar de décadas de trabajo. Por lo tanto, las bases de datos NoSQL tienen un largo camino por recorrer para ponerse al día. Así pues, merece la pena realizar una evaluación detallada de la compatibilidad con SQL.
Estos son los criterios que debe utilizar para evaluar el soporte SQL en las bases de datos NoSQL.
- Soporte del lenguaje: Qué sentencias, tipos de datos, operaciones (uniones, agrupación, agregación, ventanas, paginación, etc.)
- Soporte de indexación: Los índices son clave para el rendimiento, especialmente en las cargas de trabajo de las aplicaciones interactivas.
- Optimizador: La reescritura de consultas, la elección de la ruta de acceso correcta y la creación de la ruta de ejecución de consultas óptima es lo que convierte a SQL en un 4GL de éxito. Algunos tienen un optimizador basado en reglas, otros tienen un optimizador basado en costes, otros tienen ambos. Evaluar la calidad del optimizador es fundamental. Las típicas pruebas comparativas (TPC-C, TPC-DS, YCSB, YCSB-JSON) no le ayudarán en este caso.
- Como dice el refrán: "Hay tres cosas importantes en las bases de datos: rendimiento, rendimiento y rendimiento". Es importante medir el rendimiento de tu carga de trabajo. YCSB y la ampliada YCSB-JSON facilitará esta evaluación.
- SDK: Los completos SDK y la compatibilidad de idiomas aceleran el desarrollo.
- Soporte de herramientas de BI: Para el análisis de grandes volúmenes de datos, es importante la compatibilidad de las herramientas de BI, normalmente a través de controladores estándar de conectividad a bases de datos.
En este artículo, compararé y contrastaré el soporte del lenguaje SQL en Cassandra, CosmosDB, Couchbase y MongoDB a través de sus respectivas implementaciones. Por cierto, MongoDB no soporta SQL pero tiene algunas comandos comparativos.
He dividido el análisis en varias secciones. El formato de WordPress hace que estas tablas sean demasiado grandes. Aquí tienes una versión en PDF compacta y fácil de leer. [Haga clic en la imagen para ver el PDF].
Enfoque de soporte SQL:
| SQL | SQL es un lenguaje declarativo, cuya base son las operaciones select-join-project. |
| Cassandra | CQL: Lenguaje inspirado en SQL para Cassandra. |
| CosmosDB | Admite SQL junto con la API de MongoDB, Gremlin (para el gráfico), etc. Soporte simple select-from-where-order-by. |
| Couchbase | N1QL: SQL para JSON.
Couchbase tiene dos implementaciones de N1QL: servicio de consulta y servicio de análisis. |
| MongoDB | Consulta basada en comandos SQL simplificados y basada en Javascript. |
ENTRADA y SALIDA
| SQL | ENTRADA: Conjunto de filas (tuplas)
SALIDA: Un conjunto de filas (tuplas) |
| Cassandra | ENTRADA: Conjuntos de filas
SALIDA: Conjunto de filas |
| CosmosDB | ENTRADA: Conjuntos de JSON
SALIDA: Conjunto de JSON |
| Couchbase | ENTRADA: Conjuntos de JSON
SALIDA: Conjunto de JSON |
| MongoDB | ENTRADA: Conjuntos de JSON
SALIDA: Conjunto de JSON |
SELECT: Cláusula FROM
| SQL | Especifica las tablas de origen de datos (relaciones) |
| Cassandra | Cláusula FROM con una sola tabla permitida. Ahora se permiten joins, subconsultas o expresiones. La interpretación de la cláusula FROM es la misma que en SQL. |
| CosmosDB | La cláusula FROM admite una única colección y autouniones (igual que UNNEST en Couchbase). |
| Couchbase | Cláusula FROM con múltiples espacios clave (subconjunto de bucket), subconsultas, expresiones. Igual que SQL |
| MongoDB | db.t1.find() para una sola tabla SELECT.
db.t1.aggregate() se utiliza como marco de consulta generalizado. aggregate() puede unirse con colecciones adicionales utilizando el operador $lookup. Puede haber múltiples operadores $lookup en el marco de la tubería de agregación por lo que es el primo más cercano de la cláusula FROM de SQL. |
SELECT: Cláusula WHERE
| SQL | Criterios de selección de una fila |
| Cassandra | Expresiones booleanas estándar. Sin subconsultas. |
| CosmosDB | Igual que SQL |
| Couchbase | Expresiones booleanas estándar y subconsultas. |
| MongoDB | db.t1.find({x:10});
aggregate() tiene la cláusula $match. |
SELECT: Cláusula SELECT
| SQL | Cláusula de proyección |
| Cassandra | La cláusula SELECT es igual que SQL. |
| CosmosDB | La cláusula SELECT es igual que SQL. |
| Couchbase | La cláusula SELECT es igual que SQL. |
| MongoDB | db.t1.find({x:10}, {a:1, b:1})
Operador del proyecto $ en la cadena de agregación |
SELECT: CTE - Expresión común de tabla
| SQL | Fuente de datos definida dinámicamente (tabla, conjunto de resultados) |
| Cassandra | Sin soporte |
| CosmosDB | Sin soporte |
| Couchbase | cláusula WITH; igual que SQL (en v6.5). La CTE recursiva no está soportada |
| MongoDB | Sin soporte |
SELECT: Subconsulta
| SQL | Subconsulta: Se permiten las subconsultas en la cláusula FROM, en la cláusula WHERE, en cualquier parte de una expresión. |
| Cassandra | Sin soporte |
| Cosmosdb | Sin soporte |
| Couchbase | Admite subconsultas correlacionadas y no correlacionadas. |
| MongoDB | No soportado en find(). Puede añadir $match en la canalización, pero no es exactamente un equivalente de una subconsulta. |
SELECT: GROUP BY
| SQL | Agrupa las filas basándose en una o más expresiones. Bastante útil en informes y agregación para grupos. |
| Cassandra | Soportado; Igual que SQL. |
| Cosmosdb | No compatible. Sólo se puede realizar la agregación en todo el conjunto de resultados. |
| Couchbase | Compatible; similar a SQL. |
| MongoDB | Operador $group en la canalización aggregate() |
SELECT: Cláusula HAVING
| SQL | Filtrado tras la agregación. |
| Cassandra | Sin soporte |
| CosmosDB | Sin soporte |
| Couchbase | Cláusula HAVING; Igual que SQL |
| MongoDB | $match tras la agrupación y agregación. |
SELECT: Cláusula ORDER BY
| SQL | El orden final de los resultados producidos por el bloque de consulta |
| Cassandra | Cláusula ORDER BY; Igual que SQL. |
| Cosmosdb | Cláusula ORDER BY; Igual que SQL. |
| Couchbase | Cláusula ORDER BY; Igual que SQL. |
| MongoDB | db.t1.find().sort({a:1, b:-1});
aggregate() tiene $sort para especificar el orden de los resultados. |
SELECT: Cláusula LIMIT, OFFSET
| SQL | Se utiliza para la paginación del conjunto de resultados |
| Cassandra | "LIMIT" es compatible.
OFFSET no es compatible". |
| CosmosDB | Cláusula LIMIT (TOP) y OFFSET; similar a SQL |
| Couchbase | Cláusula LIMIT y OFFSET; Igual que SQL |
| MongoDB | skip(), limit() con find(). $offset, $limit con aggregate(). |
SELECT: Cláusula JOIN
| SQL | INNER JOIN, LEFT/RIGHT/FULL outer joins. |
| Cassandra | No se admiten las uniones. Las aplicaciones tendrán que modelar los datos para evitar las uniones o realizar las uniones en la capa de aplicación. |
| Cosmosdb | Sólo auto JOINs. No INNER/LEFT/RIGHT/etc joins. |
| Couchbase | Admite INNER, LEFT OUTER, NEST, UNNEST y RIGHT outer limitado. Misma sintaxis que SQL. La unión FULL OUTER no está soportada. |
| MongoDB | LEFT OUTER JOIN limitado sólo mediante el operador $lookup. No se pueden unir elementos de matrices o expresiones. |
SELECCIONAR: Agregación
| SQL | Agregación |
| Cassandra | Se admite la agregación simple de todo el resultado. No se admite la agregación con GROUP BY. |
| CosmosDB | Se admite la agregación simple de todo el resultado. No se admite la agregación con GROUP BY. |
| Couchbase | SUM, AVG, COUNT, MAX, MIN, VARIANCE: igual que SQL |
| MongoDB | $sum, $count, $avg con soporte de agrupación |
SELECT: funciones agregadas
| SQL | Se admite la agregación simple de todo el resultado. No se admite la agregación con GROUP BY. |
| Cassandra | Sin soporte |
| Cosmosdb | Sin soporte |
| Couchbase | Compatible con las funciones analíticas de la ventana SQL Standard en 6.5. |
| MongoDB | Sin soporte |
SELECT : Funciones de ventana (análisis/agregación)
| SQL | Funciones de ventana para ejecutar totales utilizando la cláusula OVER() |
| Cassandra | Sin soporte |
| CosmosDB | Sin soporte |
| Couchbase | Compatible con las funciones analíticas de la ventana SQL Standard en 6.5.
Ver detalles: https://www.couchbase.com/blog/json-to-insights-fast-and-easy/ https://www.couchbase.com/blog/get-a-bigger-picture-with-n1ql-window-functions-and-cte/ |
| MongoDB | Sin soporte |
INSERT: Inserción de una fila/documento.
| SQL | Insertar una sola fila |
| Cassandra | Declaración INSERT |
| CosmosDB | Inserción API |
| Couchbase | Declaración INSERT |
| MongoDB | db.t1.guardar() |
INSERT: Inserción de varias filas/documentos.
| SQL | Declaración INSERT |
| Cassandra | Sin soporte |
| Cosmosdb | Sin soporte |
| Couchbase | INSERTAR con varios documentos |
| MongoDB | db.t1.insert() |
Declaración DELETE
| SQL | Borrar uno o varios documentos |
| Cassandra | Sentencia DELETE; Igual que SQL |
| Cosmosdb | Eliminación de API |
| Couchbase | Sentencia DELETE; Igual que SQL |
| MongoDB | db.t1.delete() |
Declaración UPSERT
| SQL | INSERTAR. UPDATE si existe. |
| Cassandra | Sin soporte |
| Cosmosdb | Sin soporte |
| Couchbase | Declaración UPSERT. |
| MongoDB | Sin soporte |
Declaración UPDATE
| SQL | |
| Cassandra | UPDATE; Igual que SQL |
| CosmosDB | Actualización de la API |
| Couchbase | UPDATE; Igual que SQL |
| MongoDB | db.t1.update() |
FUSIONAR: Fusionar una relación (conjunto de filas) con otra.
| SQL | Fusionar un conjunto de filas (documentos) en otro. |
| Cassandra | Sin soporte |
| CosmosDB | Sin soporte |
| Couchbase | Sentencia MERGE, igual que SQL. |
| MongoDB | Sin soporte |
Declaración PREPARA
| SQL | Parsear, analizar y crear un plan de ejecución. |
| Cassandra | Soportado. Veo ejemplos de preparedStatement() en Java SDK.dd |
| CosmosDB | Sin soporte |
| Couchbase | Apoyado; PREPARAR |
| MongoDB | Sin soporte |
EJECUTAR
| SQL | Ejecutar una sentencia ad-hoc o preparada. |
| Cassandra | Compatible con Java. |
| Cosmosdb | Sin soporte |
| Couchbase | Soportado, similar a SQL. |
| MongoDB | Sin soporte |
SUBVENCIÓN/REVOCACIÓN
| SQL | Conceder/REVOCAR permisos para operaciones específicas en el conjunto de datos |
| Cassandra | SUBVENCIÓN, REVOCACIÓN |
| CosmosDB | Soporte API |
| Couchbase | CONCEDER FUNCIÓN, REVOCAR FUNCIÓN |
| MongoDB | ¿TBD? |
Declaración DESCRIBE
| SQL | Describe el esquema de una tabla |
| Cassandra | DESCRIBIR |
| Cosmosdb | Sin soporte |
| Couchbase | INFER describe el esquema de los documentos |
| MongoDB | Herramienta brújula - sólo gráfica. |
Sentencia TRUNCATE
| SQL | Trunca los datos de la tabla sin alterar la seguridad ni el esquema físico. |
| Cassandra | TRUNCAR |
| CosmosDB | Sin soporte |
| Couchbase | Operación FLUSH |
| MongoDB | No compatible. Solución: elimine la colección y vuelva a crearla con la misma configuración de seguridad. |
Lógica de valores (valores booleanos)
| SQL | Verdadero, Falso, NULL (Desconocido) |
| Cassandra | Verdadero, Falso, NULL (Desconocido) |
| Cosmosdb | Verdadero, Falso, NULL (Desconocido) |
| Couchbase | Verdadero, Falso, NULL (Desconocido), Ausente
https://docs.couchbase.com/server/4.0/n1ql/n1ql-language-reference/booleanlogic.html |
| MongoDB | Verdadero, Falso, NULL (Desconocido) |
Optimizador de consultas: Tipo de optimizador
| SQL | Optimizador basado en reglas y costes. Realiza reescrituras de consultas, selección de índices, ordenación de uniones, selección del tipo de unión y posición de los tabuladores (interior/exterior, construcción/probación de tablas hash). |
| Cassandra | Optimizador basado en reglas. La selección de índices para la tabla única se realiza ya que no hay uniones. |
| CosmosDB | El optimizador basado en reglas se encarga principalmente de la selección de índices. |
| Couchbase | Optimizador basado en reglas, selección de índices. Bloquea la unión de bucles anidados por defecto, pero admite la unión de hash mediante una sugerencia del usuario en la consulta. |
| MongoDB | Optimizador "basado en la forma" según la documentación. Cada nueva consulta se empareja con una consulta basada en la "forma". La primera vez que se ejecuta una consulta, el optimizador selecciona el índice, pero cuando hay varios candidatos, ejecuta varias consultas simultáneamente para ver quién devuelve primero los resultados. |
Optimizador de consultas: Selección de índices
| SQL | Sí |
| Cassandra | Sí |
| CosmosDB | Sí |
| Couchbase | Sí |
| MongoDB | Sí |
Optimizador de consultas: Reescritura de consultas
| SQL | Reescribir partes de la consulta en equivalentes lógicos para mejorar el rendimiento. Por ejemplo, reescritura de subconsultas, plegado de vistas, conversión de tipos de unión, evaluación de expresiones constantes, etc. |
| Cassandra | Ninguno |
| Cosmosdb | No se conocen reescrituras |
| Couchbase | Reescritura básica de consultas. De LEFT OUTER a INNER cuando proceda, evaluación de expresiones constantes. |
| MongoDB | Ninguno |
Optimización de consultas: Tipo JOIN
| SQL | Elija el índice más eficaz entre los tipos de unión disponibles. |
| Cassandra | No aplicable, ya que no se admiten uniones. |
| CosmosDB | No está claramente documentado. |
| Couchbase | Bucle anidado por defecto. Hash join por pista de usuario. |
| MongoDB | Sólo se admite el bucle anidado. |
Apoyo a las TRANSACCIONES.
| SQL | Soporte ACID con soporte multi-fila y multi-estado. |
| Cassandra | No |
| Cosmosdb | Sí |
| Couchbase | No |
| MongoDB | Sí, en 4.0 |
Índices
| SQL | Estructuras de datos que se mantienen para acelerar el rendimiento de las consultas. Los índices son |
| Cassandra | Admite índices primarios, secundarios y de matriz. Necesidad de instalar e indexar los datos en SOLR para un índice de búsqueda. |
| CosmosDB | Indexa todo por defecto: escalares, matrices. No soporta el índice de búsqueda. |
| Couchbase | Admite índices primarios, secundarios, compuestos, funcionales, adaptativos, de búsqueda, espaciales, particionados y de réplica. Los índices son finalmente coherentes. |
| MongoDB | Admite índices primarios, secundarios, compuestos, de búsqueda, espaciales, particionados y de réplica. El índice de búsqueda se crea de forma simplista en un árbol B. |
SQL: Soporte de tipos de datos.
| SQL | Amplio soporte de tipos de datos numéricos, de caracteres y de fecha-hora. |
| Cassandra | Numérico, decimal, doble. Int, float, varint, Timestamp, collection (set, list) |
| CosmosDB | Tipos de datos JSON: numéricos, cadenas, booleanos, objetos, matrices |
| Couchbase | Tipos de datos JSON: numéricos, cadenas, booleanos, objetos, matrices |
| MongoDB | Tipos de datos JSON: numérico, cadena, booleano, objeto, matrices y extensiones personalizadas para el tipo de datos timestamp. |
Conclusión:
Las populares bases de datos NoSQL han intentado ampliar y soportar el SQL declarativo para el modelo de datos y las arquitecturas respectivas. Por lo tanto, es importante entender las capacidades, las limitaciones de las características y la arquitectura durante la evaluación.
Referencias:

[...] las transacciones y su semántica. SQL como lenguaje de consulta ha sido irrazonablemente eficaz incluso en los sistemas de bases de datos NoSQL. Sin embargo, pocos sistemas de bases de datos NoSQL soportan transacciones. Los que soportan vienen con un largo [...]