nosql - foreign - cassandra relations
MAX(), DISTINTO y grupo por en Cassandra (4)
Estoy tratando de remodelar una base de datos SQL Cassandra de tal manera que, puedo encontrar el equivalente de Cassandra para las consultas SQL. Yo uso CQL 3 y Cassandra v1.2. Modelé el diseño de db en cassandra para que admita el orden de las cláusulas y las tablas desnormalizadas para admitir la operación de unión. Sin embargo, estoy en el mar cuando se trata de los equivalentes DISTINCT, SUM () y GROUPBY.
SELECT a1,MAX(b1) FROM demo1 group by a1.
SELECT DISTINCT (a2) FROM demo2 where b2=''sea''
SELECT sum(a3), sum(b3) from demo3 where c3=''water'' and d3=''ocean''
Esto es como un showstopper a mi trabajo durante los últimos días. ¿Hay alguna forma en Cassandra de que pueda modelar el esquema db para que sea compatible con este tipo de consultas? No puedo pensar de ninguna manera en Cassandra. ¿Cómo se implementan estas consultas utilizando Cassandra?
Leí que una capa de colmena sobre Cassandra puede hacer que estas consultas funcionen. Me pregunto si esa es la única forma en que Cassandra puede admitir este tipo de consultas. Por favor, asesorar sobre cualquier otro método posible ..
Aunque esta es una pregunta antigua, aparece en los resultados de búsqueda de Google bastante alto. Así que quería dar una actualización.
Cassandra 2.2+ admite funciones definidas por el usuario y agregados definidos por el usuario. ADVERTENCIA : esto no significa que ya no tenga que hacer el modelado de datos (como lo señaló @Theo), sino que le permite preprocesar ligeramente sus datos al recuperarlos.
SELECCIONAR DISTINTO (a2) DESDE demo2 donde b2 = ''mar''
Para implementar DISTINCT
, debe definir una función y un agreggate. Llamaré a la función y al agregado uniq
lugar de distinct
para enfatizar el hecho de que es definido por el usuario.
CREATE OR REPLACE FUNCTION uniq(state set<text>, val text)
CALLED ON NULL INPUT RETURNS set<text> LANGUAGE java
AS ''state.add(val); return state;'';
CREATE OR REPLACE AGGREGATE uniq(text)
SFUNC uniq STYPE set<text> INITCOND {};
Entonces lo usas como sigue:
SELECT uniq(a2) FROM demo2 where b2=''sea'';
SELECCIONE la suma (a3), la suma (b3) de la demostración3 donde c3 = ''agua'' y d3 = ''océano''
SUM
se proporciona fuera de la caja y funciona como usted esperaría. Ver system.sum
.
SELECCIONE a1, MAX (b1) DEL grupo demo1 por a1
GROUP BY
es complicado. En realidad, no hay manera de agrupar filas de resultados por alguna columna. Pero lo que puede hacer es crear un map<text, int>
y agruparlos manualmente en el mapa. Basado en un ejemplo del blog de Christopher Batey, group-by y max:
CREATE OR REPLACE FUNCTION state_group_and_max(state map<text, int>, type text, amount int)
CALLED ON NULL INPUT
RETURNS map<text, int>
LANGUAGE java AS ''
Integer val = (Integer) state.get(type);
if (val == null) val = amount; else val = Math.max(val, amount);
state.put(type, val);
return state;
'' ;
CREATE OR REPLACE AGGREGATE state_group_and_max(text, int)
SFUNC state_group_and_max
STYPE map<text, int>
INITCOND {};
Entonces lo usas como sigue:
SELECT state_group_and_max(a1, b1) FROM demo1;
Notas
- Como se mencionó anteriormente, aún tiene que invertir algo de tiempo en el modelado de datos, no use estas características en exceso.
- Tiene que configurar
enable_user_defined_functions=true
en sucassandra.yaml
para habilitar las funciones - Puede sobrecargar las funciones para admitir la agrupación por columnas de diferentes tipos.
Referencias:
Cassandra 3.10 ahora es compatible con el grupo por clave de partición y clave de agrupamiento. Puede consultar este enlace para más detalles.
Cassandra no soporta operaciones como esta. Puede usar algo como Hive en la parte superior o hay un producto (no gratuito) de Acunu que puede hacer lo que necesite.
La otra solución es hacer el trabajo usted mismo. Por ejemplo, puedes sumar cosas leyendo todos los datos de ciertas filas y sumando. O mantén un contador de Cassandra para incrementar sobre la marcha.
Con Cassandra, resuelve este tipo de problemas haciendo más trabajo cuando inserta sus datos, lo que parece que sería lento, pero Cassandra está diseñada para escrituras rápidas, y probablemente vaya a leer los datos muchas veces más que usted. Escríbalo para que tenga sentido cuando considere todo el sistema.
No puedo decirle exactamente cómo crear sus tablas para modelar su problema porque dependerá mucho de los detalles. Debe calcular un esquema que le permita obtener los datos sin realizar agregaciones sobre la marcha. Piense en cómo crearía vistas para las consultas en un RDBMS, y luego trate de pensar cómo insertaría los datos directamente en esas vistas, no en las tablas subyacentes. Así es como modelas las cosas en Cassandra.