cassandra - costo - cql que es
¿Cómo funcionan los índices secundarios en Cassandra? (2)
Supongamos que tengo una familia de columnas:
CREATE TABLE update_audit (
scopeid bigint,
formid bigint,
time timestamp,
record_link_id bigint,
ipaddress text,
user_zuid bigint,
value text,
PRIMARY KEY ((scopeid, formid), time)
) WITH CLUSTERING ORDER BY (time DESC)
Con dos índices secundarios, donde record_link_id
es una columna de alta cardinalidad:
CREATE INDEX update_audit_id_idx ON update_audit (record_link_id);
CREATE INDEX update_audit_user_zuid_idx ON update_audit (user_zuid);
Según mi conocimiento, Cassandra creará dos familias de columnas ocultas como:
CREATE TABLE update_audit_id_idx(
record_link_id bigint,
scopeid bigint,
formid bigint,
time timestamp
PRIMARY KEY ((record_link_id), scopeid, formid, time)
);
CREATE TABLE update_audit_user_zuid_idx(
user_zuid bigint,
scopeid bigint,
formid bigint,
time timestamp
PRIMARY KEY ((user_zuid), scopeid, formid, time)
);
Los índices secundarios de Cassandra se implementan como índices locales en lugar de distribuirse como tablas normales. Cada nodo solo almacena un índice para los datos que almacena.
Considere la siguiente consulta:
select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
- ¿Cómo se ejecutará esta consulta ''bajo el capó'' en Cassandra?
- ¿Cómo un índice de columna de alta cardinalidad (
record_link_id
) afectará su rendimiento? - ¿Cassandra tocará todos los nodos para la consulta anterior? ¿Por qué?
- ¿Qué criterios se ejecutarán primero, la tabla base partición_clave o el índice partición_clave secundaria? ¿Cómo entrecruzará Cassandra estos dos resultados?
Consulta con solo índice secundario también es posible en Cassandra 2.x
seleccione * de update_audit donde record_link_id = 9897;
Pero esto tiene un gran impacto en la obtención de datos, ya que lee todas las particiones en un entorno distribuido. Los datos obtenidos por esta consulta tampoco son consistentes y no se pueden retransmitir.
Sugerencia:
El uso del índice secundario se considera una consulta DIRT desde la vista del modelo de datos NoSQL.
Para evitar un índice secundario, podríamos crear una nueva tabla y copiar datos en ella. Como esta es una consulta de la aplicación, las Tablas se derivan de consultas.
select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
¿Cómo funcionará la consulta anterior internamente en cassandra?
Esencialmente, todos los datos para la partición scopeid=35
y formid=78005
se devolverán y luego se filtrarán por el índice record_link_id
. record_link_id
entrada record_link_id
para 9897
e intentará hacer coincidir las entradas que coincidan con las filas devueltas donde scopeid=35
y formid=78005
. Se devolverá la intersección de las filas para las claves de partición y las claves de índice.
¿Cómo afectará el índice de columna de cardinalidad alta (record_link_id) el rendimiento de la consulta para la consulta anterior?
Los índices de cardinalidad alta esencialmente crean una fila para (casi) cada entrada en la tabla principal. El rendimiento se ve afectado, porque Cassandra está diseñada para realizar lecturas secuenciales para los resultados de la consulta. Una consulta de índice esencialmente obliga a Cassandra a realizar lecturas aleatorias . A medida que aumenta la cardinalidad de su valor indexado, también aumenta el tiempo necesario para encontrar el valor consultado.
¿Cassandra tocará todos los nodos para la consulta anterior? ¿POR QUÉ?
No. Solo debe tocar un nodo que sea responsable de las scopeid=35
y formid=78005
. Los índices también se almacenan localmente, solo contienen entradas que son válidas para el nodo local.
la creación de índices sobre columnas de alta cardinalidad será el modelo de datos más rápido y mejor
El problema aquí es que el enfoque no se escala y será lento si update_audit
es un conjunto de datos grande. El MVP Richard Low tiene un gran artículo sobre índices secundarios ( The Sweet Spot For Cassandra Secondary Indexing ), y particularmente sobre este punto:
Si su tabla fuera significativamente más grande que la memoria, una consulta sería muy lenta incluso para devolver solo unos pocos miles de resultados. Devolver potencialmente a millones de usuarios sería desastroso aunque parezca ser una consulta eficiente.
...
En la práctica, esto significa que la indexación es más útil para devolver decenas, tal vez cientos de resultados. Tenga esto en cuenta la próxima vez que considere usar un índice secundario.
Ahora, su enfoque de la primera restricción por una partición específica ayudará (ya que su partición debe encajar en la memoria). Pero creo que la mejor opción aquí sería hacer de record_link_id
una clave de agrupación, en lugar de confiar en un índice secundario.
Editar
¿Cómo se puede aumentar el índice de índice de cardinalidad baja cuando hay millones de usuarios incluso cuando proporcionamos la clave principal?
Dependerá de la anchura de sus filas. Lo complicado de los índices de cardinalidad extremadamente bajos, es que el% de filas devueltas suele ser mayor. Por ejemplo, considere una tabla de users
fila ancha. Usted restringe la clave de partición en su consulta, pero todavía hay 10,000 filas devueltas. Si su índice está en algo como gender
, su consulta tendrá que filtrar aproximadamente la mitad de esas filas, lo que no funcionará bien.
Los índices secundarios tienden a funcionar mejor en (a falta de una mejor descripción) la cardinalidad "en la mitad del camino". Usando el ejemplo anterior de una tabla de users
fila ancha, un índice en el country
o state
debería tener un rendimiento mucho mejor que un índice en gender
(asumiendo que la mayoría de esos usuarios no viven todos en el mismo país o estado).
Editar 20180913
Para su respuesta a la primera pregunta "¿Cómo funcionará internamente la consulta anterior en cassandra?", ¿Sabe cuál es el comportamiento cuando consulta con paginación?
Considere el siguiente diagrama, tomado de la documentación del controlador de Java (v3.6):
Básicamente, la paginación hará que la consulta se separe y regrese al clúster para la siguiente iteración de resultados. Sería menos probable que se agote el tiempo de espera, pero el rendimiento tendrá una tendencia descendente, proporcional al tamaño del conjunto total de resultados y al número de nodos en el clúster.
TL; DR; Cuantos más resultados solicitados se extiendan a más nodos, más tardará.