SQL existe desde hace muchísimo tiempo. Es una forma muy intuitiva y eficiente de procesar datos estructurados y ha sido la elección para las bases de datos durante muchos años. Sin embargo, con el mundo de BIG DATA, los datos se han velocidad, variedad y volumen. SQL puede abordar los 2 "v"Está bien con las optimizaciones: "velocidad" y "volumen". De hecho, muchos nuevos dielectos de SQL (N1QL, Spark, U-SQL, Impala, Drill y más) están haciendo exactamente eso. Sin embargo, "variedad"es otro juego. Los Big Data son complejos en el nuevo mundo; tienen un esquema impredecible, en constante evolución, irregular, valores dispersos y estructuras profundamente anidadas. ¡Para eso SQL necesita ampliarse!
Bueno, ¡estoy súper emocionado de informar que hemos construido N1QL en Couchbase Server 4 para abordar exactamente estos problemas! N1QL puede recorrer fácilmente las estructuras complejas en JSON (el estándar de serialización de-facto para datos complejos). Usando N1QL, puedes trabajar no sólo con NULLs sino también con atributos que son FALTA en varias formas de JSON que procesas. O puede utilizar operadores como CUALQUIERA para consultar matrices incrustadas en documentos JSON. O puede utilizar comandos como UNNEST & NEST que puede acoplar o desacoplar matrices anidadas. Hay demasiadas de estas potentes extensiones para contarlas aquí, así que no lo haré. En su lugar voy a mostrar una joya escondida que fue publicada originalmente aquí por Gerald. Esta gema es muy útil con agregados si está utilizando N1QL. vs una base de datos relacional como SQL Server.
Una de las grandes ventajas de N1QL es su capacidad para entender los tipos de array. Las funciones de agregación como MAX() no son revolucionarias pero con las adiciones de anidamiento y arreglos, algo tan simple como MAX() puede ser super poderoso. Una nota antes de entrar en materia - Voy a escoger TSQL y SQL Server ya que contribuí a TSQL en mi vida pasada en Microsoft. Sin embargo, esto es aplicable a Oracle, Postgres, Mysql, Informix o DB2 y más ... Ok así: Imagínese tratando de encontrar atributos del producto que tiene el precio MAX. En SQL Server que es bastante simple consulta a escribir utilizando TSQL;
|
1 2 3 |
SELECT productID, name FROM t1 WHERE price = (SELECT MAX(price) FROM t1) GO |
Así está bien. Aquí está el resultado - el producto con el precio más alto es el producto llamado "c" con ID 3.
|
1 2 3 4 |
productID name ----------- ----------------------------------------------------------------- 3 c |
Este es el aspecto del plan de ejecución. Básicamente, el plan de ejecución busca el valor de precio MAX. Una vez que tiene el valor, es un bucle anidado join para buscar los otros atributos del producto en la tabla como productID y name.
|
1 2 3 4 5 6 7 8 |
Stmt Text --------------------------------------------------------------------------------------------- select productID, name from t1 where price = (select max(price) from t1) |--Nested Loops(Inner Join, WHERE:([Expr1004]=[test].[dbo].[t1].[price])) |--Stream Aggregate(DEFINE:([Expr1004]=MAX([test].[dbo].[t1].[price]))) | |--Clustered Index Scan(OBJECT:([test].[dbo].[t1].[PK__t1__2D10D14A7FD17868])) |--Clustered Index Scan(OBJECT:([test].[dbo].[t1].[PK__t1__2D10D14A7FD17868])) |
Sin embargo, N1QL tiene aquí una gran ventaja. Puesto que puede procesar MAX() con matrices, puede devolver todos los atributos del documento sin un análisis adicional.
|
1 |
SELECT MAX([price, {productID, name]) FROM test; |
O puede simplemente devolver el documento completo utilizando la siguiente consulta;
|
1 |
SELECT MAX([price, test]) FROM test; |
Veamos el plan de ejecución de la consulta N1QL. Aquí viene el spoiler: se ve una sola operación FETCH que puede realizar el MAX y la proyección se realiza sin un segundo FETCH.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
cbq>explain select MAX([price,test])from test; { "requestID":"b735ce5f-700c-4740-a065-6d4ba681129f", "signature":"json", "results":[ { "#operator":"Sequence", "~children":[ { "#operator":"PrimaryScan", "index":"#primary", "keyspace":"test", "namespace":"default", "using":"gsi" }, { "#operator":"Parallel", "~child":{ "#operator":"Sequence", "~children":[ { "#operator":"Fetch", "keyspace":"test", "namespace":"default" }, { "#operator":"InitialGroup", "aggregates":[ "max([(`test`.`price`), `test`])" ], "group_keys":[] } ] } }, { "#operator":"IntermediateGroup", "aggregates":[ "max([(`test`.`price`), `test`])" ], "group_keys":[] }, { "#operator":"FinalGroup", "aggregates":[ "max([(`test`.`price`), `test`])" ], "group_keys":[] }, { "#operator":"Parallel", "~child":{ "#operator":"Sequence", "~children":[ { "#operator":"InitialProject", "result_terms":[ { "expr":"max([(`test`.`price`), `test`])" } ] }, { "#operator":"FinalProject" } ] } } ] } ], "status":"success", "metrics":{ "elapsedTime":"1.8224ms", "executionTime":"1.7614ms", "resultCount":1, "resultSize":2347 } } |
Aunque, este es un truco muy bueno y una gran ganancia de rendimiento, sólo hemos arañado la superficie de lo que N1QL es capaz de hacer. Hay mucho más por descubrir con N1QL. Puedes empezar a usar Couchbase Server y N1QL aquí con la herramienta guía de iniciación.
———————————————————
Por cierto si quieres probar esto con SQL Server 2016 y Couchbase 4, aquí tienes los scripts para verlo tú mismo en acción;
Script SQL Server
Nota: Ejecute esto en una base de datos llamada "test".
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
create table t1(productID int primary key, price int, name varchar(128)); go insert into t1(productID,price,name) values(1,10,'a'); insert into t1(productID,price,name) values(2,9,'b'); insert into t1(productID,price,name) values(3,12,'c'); insert into t1(productID,price,name) values(4,11,'d'); insert into t1(productID,price,name) values(5,1,'e'); go set statistics profile on go select max(price),productID,name from t1 go --Msg 8120, Level 16, State 1, Line 10 --Column 't1.productID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. select productID, name from t1 where price = (select max(price) from t1) go |
Este es el script del servidor Couchbase
Nota: cree un cubo llamado "test".
insert into prueba(clave,valor) values("1",{productoID:1, precio:10, nombre:'a'});
|
1 2 3 4 5 6 7 8 9 |
insert into test(key,value) values("1",{productID:1, price:10, name:'a'}); insert into test(key,value) values("2",{"productID":2, "price":9, "name":"b"}); insert into test(key,value) values("3",{"productID":3, "price":12, "name":"c"}); insert into test(key,value) values("4",{"productID":4, "price":11, "name":"d"}); insert into test(key,value) values("5",{"productID":5, "price":1, "name":"e"}); create primary index on test; select max(price, productID, name) from t1; select max([price, test]) from test; explain select max([price, test]) from test; |