La Mala : Particionamiento
Una de las cosas difíciles a las que acostumbrarse al principio es que sin ningún índice, las consultas que abarcan filas pueden (muy) ser malas. Sin embargo, pensar en nuestro modelo de almacenamiento no es sorprendente. La estrategia que utiliza Cassandra para distribuir las filas entre los hosts se denomina Particionamiento.
Partición es el acto de dividir el rango de rowkeys la asignación en el «token ring», que también asigna la responsabilidad de un segmento (es decir, la partición) de la rowkey rango a cada host. Probablemente haya visto esto cuando inicializó su clúster con un «token». El token le da al host una ubicación a lo largo del anillo de tokens, que asigna la responsabilidad de una sección del rango de tokens. El particionamiento es el acto de asignar la clave de fila al rango de tokens.
Hay dos particionadores principales: Aleatorio y Preservación de Orden. Tienen un nombre apropiado. El RandomPartitioner convierte las teclas de fila en tokens. Con RandomPartitioner, el token es un hash de la rowkey. Esto hace un buen trabajo al distribuir uniformemente sus datos a través de un conjunto de nodos, pero hace que consultar un rango del espacio de las teclas de fila sea increíblemente difícil. De solo un valor de «llave de fila inicial» y un valor de «llave de fila final», Cassandra no puede determinar qué rango del espacio de token necesita. Esencialmente necesita realizar un » escaneo de tabla «para responder a la consulta, y un» escaneo de tabla » en Cassandra es malo porque necesita ir a cada máquina (lo más probable es que TODAS las máquinas si tiene una buena función hash) para responder a la consulta.
Lo bueno : Índices secundarios
Cassandra proporciona un mecanismo de indexación nativo en Índices Secundarios. Los índices secundarios funcionan fuera de los valores de las columnas. Se declara un índice secundario en una familia de columnas. Datastax tiene buena documentación sobre el uso. Bajo el capó, Cassandra mantiene una» familia de columnas ocultas » como el índice. (Vea la presentación de Ed Anuff para detalles específicos) Dado que Cassandra no mantiene la información del valor de columna en ningún nodo, y los índices secundarios están en el valor de las columnas (en lugar de las teclas de fila), aún debe enviarse una consulta a todos los nodos. Además, no se recomiendan índices secundarios para conjuntos de alta cardinalidad. Todavía no he mirado, pero asumo que esto se debe al modelo de datos utilizado dentro de la «familia de columnas ocultas». Si la familia de columnas ocultas almacena una fila por valor único (con teclas de fila como columnas), significaría escanear las filas para determinar si están dentro del rango de la consulta.
De la presentación de Ed:
- No se recomienda para valores de cardinalidad altos(es decir, marcas de tiempo,fechas de nacimiento, palabras clave, etc.)
- Requiere al menos una comparación de igualdad en una consulta
- Sin clasificar: los resultados están en orden de tokens, no en orden de valor de consulta
- Limitado a buscar en tipos de datos, Cassandra entiende de forma nativa
Con todo lo dicho, los índices secundarios funcionan fuera de la caja y hemos tenido un buen éxito usándolos en valores simples.
Lo feo: Hágalo usted mismo ( Bricolaje) / Filas anchas
Ahora, la belleza está en el ojo del espectador. Una de las cosas hermosas de NoSQL es la simplicidad. Las construcciones son simples: Espacios de claves, Familias de Columnas, Filas y Columnas. Sin embargo, mantenerlo simple significa que a veces necesita tomar las cosas en sus propias manos.
Este es el caso de los índices de filas anchas. Utilizando el modelo de almacenamiento de Cassandra, es fácil crear sus propios índices donde cada clave de fila se convierte en una columna en el índice. Esto a veces es difícil de entender, pero imaginemos que tenemos un caso en el que queremos seleccionar a todos los usuarios en un código postal. La familia de columnas de usuarios principales está marcada en userid, el código postal es una columna en cada fila de usuarios. Podríamos usar índices secundarios, pero hay bastantes códigos postales. En su lugar, podríamos mantener una familia de columnas con una sola fila llamada «idx_zipcode». Entonces podríamos escribir columnas en esta fila de la forma «zipcode_userid». Dado que las columnas se almacenan en orden ordenado, es rápido consultar todas las columnas que comienzan con «18964» (por ejemplo, podríamos usar 18964_ y 18964_ZZZZZZ como valores de inicio y fin).
Una desventaja obvia de este enfoque es que las filas son autónomas en un host. (de nuevo a excepción de las réplicas) Esto significa que todas las consultas van a golpear un solo nodo. Aún no he encontrado una buena respuesta para esto.