Estas en: Home > column

Entradas etiquetadas con column

Logo Cassandra

Cassandra 2.x y PHP para desarrolladores SQL: El modelo de datos

0

Si has trabajado con una base de datos relacional tal vez te resulte algo confuso al principio comprender el modelo de datos que usa Cassandra, intentaré ser lo más claro posible, pero si te surgen preguntas no dudes en dejarlas en los comentarios.

 

Columns

El elemento más básico de la base de datos Cassandra es la columna, se compone de tres elementos: nombre de la columna, valor y timestamp. Os muestro un ejemplo como un array:

array(
  "nombre" => "email",
  "valor" => "webmaster@localhost.com",
  "timestamp" => time(),
);

Cassandra añade el timestamp automáticamente, con lo que otra forma de representarlo es como un conjunto clave:valor:

nombre_columna:valor

Super columnas (En desuso) y Columnas Compuestas

Las super columnas son un conjunto de columnas con sus correspondientes valores:

array(
  "nombre_superColumna" => array(
    "usuario1" => array(
      "nombre" => "email",
      "valor" => "webmaster@localhost.com",
      "timestamp" => time()
    ),
    "usuario2" => array(
      "nombre" => "email",
      "valor" => "email@email.com",
      "timestamp" => time()
    ),
    "usuario3" => array(
      "nombre" => "email",
      "valor" => "otroemail@otroemail.com",
      "timestamp" => time()
    ),
  ),
)

Las super columnas tienen algunos problemas de rendimiento, sobre todo al ordenarlas. Para solucionarlo se crearon las columnas compuestas que se benefician de los comparadores compuestos, y sobretodo, de CQL 3 (Cassandra Query Language).

Familia de columnas

Es el conjunto de columnas o super columnas. Me explico:

Las column Family o  familia de columnas se puede configurar de dos maneras: como Super o como Standard. Si se elige la opción Standard, en la column family solo se podrán guardar columnas, no super columnas. En cambio si la column family está configurada como Super podrá guardar, además de las columnas, las super columnas. Esta flexibilidad permite jugar con la base de datos y adaptarla a nuestras necesidades.

Ejemplo:

array(
  "name" => "ColumnFamily",
  array( "name" => "SuperColumn",
    array( "colums" )
  ),
)

Keyspace

El keyspace es nuestra base de datos, donde alojaremos todas las columFamilies que necesitemos.

Ejemplo:

array(
  "name" => "keyspace",
  array("name" => "columnFamily",
    array(
      [...]
    ),
  ),
)
Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: phpCassa (III)

4

Ya he tratado casi en su totalidad las funciones más básicas de PHPCassa y Cassandra, con lo que ya tendrás un conocimiento suficientemente amplio de lo que se puede hacer con ellos, el resto dependerá de la evolución de la BD y de las librerías (y de la experiencia que tengas xP).

Hoy trataré varios temas que por las consultas realizadas por varios usuarios se merece un post aparte en el que se pueda tratar de una forma más amplia. Estos temas son: ordenar registros, crear keys para los registros y contar registros.

 

ORDENAR REGISTROS

Cassandra dispone de varios tipos de comparadores y subcomparadores para ordenar los registros. El más habitual es UTF-8 pero hay varios más. Si vamos a Cassandra Cluster Admin y accedemos al formulario de creación de columns family, podremos pasar el ratón por los interrogantes que hay a la izquierda de los campos para poder ver los diferentes tipos de comparadores:

Tipos de comparadores

Tipos de comparadores

Como puedes ver, estos comparadores le dicen a Cassandra como ordenar los registros. Si has seguido este tutorial ya conocerás al menos uno de los comparadores (utf-8) por tanto vamos a ver como ordena Cassandra los registros con este comparador.

Para este primer ejemplo vamos a crear una column family llamada column_family_order_utf8 de tipo standard y el tipo de comparador UTF8Type.

Vamos a nuestro archivo test.php y escribimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. foreach($data as $key => $value){
  31. $cass->guardar('column_family_order_utf8', $key, $value);
  32. }

Este código guardará un array desordenado en nuestra column family. Una vez ejecutado el script accedemos a Cassandra Cluster Admin y visualizamos los registros de column_family_order_utf8, nos mostrará el siguiente resultado:

Listado de los registros guardados

Listado de los registros guardados

Como puedes observar los registros no se han ordenado, sin embargo cada una de las columns de cada registro sí están ordenadas por orden alfabético. Esto sucede porque los comparadores no ordenan por keys o claves de los registros sino por columns, aunque hay un caso especial, si la column family es super los registros si estarán ordenados. Veamoslo.

Creamos una column family llamada column_family_utf8_super con el tipo de comparador UTF8Type y el tipo de column family como super. En nuestro archivo test.php añadimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. $cass->guardar('column_family_order_utf8_super', 'databases', $data);

Una vez ejecutado este script nos vamos a nuestra column family y nos mostrará lo siguiente:

Listado de registros en la column family

Listado de registros en la column family

Como puedes observar ahora sí están ordenados los registros, pero claro ahora están dentro de una super column.

En Cassandra la ordenación se realiza a las columnas del registro o los registros dentro de las super columns, si creasemos otra super column, esta no se ordenaría con respecto a la ya creada, ‘databases’.

Aunque esta ordenación puede ser útil y totalmente funcional, para los desarrolladores que vengan de las bases de datos relacionales les puede resultar confuso. Por ejemplo, para guardar los comentarios de un post de un blog podríamos utilizar este tipo de ordenación perfectamente, ya que podemos utilizar el id del post como key de la super column (el ‘databases’ de la imagen anterior se sustituiría por el id del post) y el timestamp (como este 1337787675.32246500) para la key de los registros. De esta forma tendríamos ordenados los comentarios por tiempo y por post. Si quisieramos recuperar los comentarios de un post concreto solo tendríamos que pasarle al método correspondiente el id del post como key de la super column.

¿Y si quisieramos guardar los post del blog? En este caso una column family super nos lo podría resolver indicando como key de la super columnposts‘  y utilizando como key en los registros el timestamp. Pero si quisieramos hacer busquedas utilizando indices secundarios una column family super no nos valdría, ya que los indices secundarios no funcionan en ellas.

Para ello habría que crear una column family standard para los post, que nos permitirá usar los indices secundarios, y una column family super para guardar las keys de los post dentro de una super column con key, por ejemplo, ‘key_posts‘. Para hacer la consulta habría que recuperar las keys de los posts a mostrar en primer lugar, y después, utilizando un método de PHPCassa que aun no hemos usado recuperar los registros correspondientes a esas keys.

El método que deberíamos añadir a nuestro archivo cassandra.php sería el siguiente:

 

  1. <?php
  2.  
  3. function obtenerMultiplesRegistros($name_columnFamily, $multiKeys, $super_column = ''){
  4.  
  5. if (!empty($super_column)){
  6. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  7. $result = $column_family->multiget_super_column($multiKeys, $super_column);
  8. }
  9. else{
  10. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  11. $result = $column_family->multiget($multiKeys);
  12. }
  13.  
  14. return $result;
  15.  
  16. }

 

A este método le pasamos el nombre de la column family standard donde hemos guardado los posts y un array con las keys a recuperar, nos devolverá un array con los datos de cada uno de los posts que le hemos pedido… y en el orden en el que le hayamos pasado las keys a recuperar.

Existe otra forma de ordenar registros, pero además de que en versiones posteriores de Cassandra desaparecerá y provoca problemas de rendimiento, yo no la recomiendo, ya que pierdes todos los beneficios que ofrece Cassandra. Aun así os dejo un link para que le echéis un ojo xD:

http://ria101.wordpress.com/2010/02/22/cassandra-randompartitioner-vs-orderpreservingpartitioner/

Y os dejo otro link para que tengais algo más de información respecto a ordenar registros en Cassandra:

http://ayogo.com/blog/2010/04/09/sorting-in-cassandra/

 

CREAR CLAVES O KEYS PARA LOS REGISTROS

Como has podido ver en el apartado anterior, para ordenar los registros es muy importante tener una key de cada registro que sea única y siempre vaya en orden. Esto las bases de datos relacionales nos lo dan ya hecho, sin embargo en las bases de datos no-sql esto no es así.

Las bases de datos no-sql se crearon para optimizar la lectura y escritura de los registros en la base de datos, esto provocó que algunas funcionalidades muy útiles en las bases relaciones no tuvieran cabida en las no-sql. Por tanto para mantener en orden los registros debemos crear nosotros nuestras propias claves.

PHPCassa dispone de un método para crear una clave aleatoria basada en el timestamp.

Para utilizarla primero añadiremos la clase a nuestra lista:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\SuperColumnFamily;
  6. use phpcassa\ColumnSlice;
  7. use phpcassa\SystemManager;
  8. use phpcassa\Schema\StrategyClass;
  9. use phpcassa\Index\IndexExpression;
  10. use phpcassa\Index\IndexClause;
  11. use phpcassa\UUID;

Ahora crearemos un nuevo método en nuestro archivo cassamdra.php que devolverá la clave:

 

  1. <?php
  2.  
  3. public function obtenerUuid(){
  4.  
  5. $util = new UUID;
  6.  
  7. return $util->import($util->uuid1());
  8. }

 

Como me está quedando un post muy largo os voy a dejar algo de deberes xD. Sería interesante probarlo tanto con column families standard y super, además de con un tipo de comparador UTF8Type y TimeUUIDType.

Como el chorro de letras y números que devuelve es muy poco legible yo suelo utilizar mi propio sistema de claves, normalmente utilizo el microtime() de php y un par de ids de lo que se esté guardando: el id del usuario, el id de lo que se ha creado, etc. Algo que lo diferencie del resto. Para la clave primero pongo los segundos que devuelve microtime() y después los microsegundos. Para que os hagais una idea sería algo así:

$key = $segundos . ‘.’ . $microsegundos . ‘_’ . $id_post . ‘_’ . $id_usuario;

De esta forma le estamos dando una clave para los ejemplos del anterior apartado, más concretamente para los comentarios en un post.

 

CONTAR REGISTROS

El último apartado de este post. Contar registros. Esto es algo que Cassandra no lleva muy bien, sobre todo con grandes cantidades de información.

Cassandra cuando recibe una petición de lectura/escritura utiliza unas tablas en memoria llamadas memtables (el que le puso el nombre de rompió la cabeza pensando). Cuantas más peticiones reciba Cassandra más memtables creará, de esta forma permitirá una cierta consistencia de la información almacenada en la base de datos.

Cuando le pedimos a phpCassa que nos devuelva el número de registros en una column family o en una super column concreta, lo que está haciendo en realidad es hacer una petición a Cassandra de todos los registros que haya en la column family o en la super column. Cuando esto ocurre Cassandra guardará estos registros en la RAM del servidor antes de enviarlos a phpCassa, y sí Cassandra no cuenta los registros, porque no está pensada para eso, es phpCassa la que cuenta los registros y te devuelve el número concreto.

El método que utiliza phpCassa para contar registros es el que os muestro a continuación, dentro de un método para añadir al archivo cassandra.php:

 

  1. <?php
  2.  
  3. public function contar_registros($name_columnFamily, $key, $super_column='', $range_start='', $range_end=''){
  4.  
  5. $column_slice = new ColumnSlice($range_start, $range_end);
  6.  
  7. if (!empty($super_column)){
  8. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  9. $result = $column_family->get_subcolumn_count($key, $super_column, $column_slice);
  10. }
  11. else{
  12. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  13. $result = $column_family->get_count($key, $column_slice);
  14. }
  15.  
  16. return $result;
  17.  
  18. }

 

Esta forma de contar registros provoca que Cassandra consuma todos los recursos de RAM del servidor, con lo que no os la recomiendo.

La mejor manera de contar registros con Cassandra es utilizar una column family con contadores, de tal forma que en nuestro código cada vez que se guarde un registro en la bd se aumente el contador que lleva la cuenta de los registros guardados. En el caso de que se eliminen, habría que disminuirlo. Y en el caso de que el registro se esté actualizando controlar que no aumente el contador xD.

Cualquier duda que tengais intentaré responderla lo mejor posible en los comentarios.

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: phpCassa (II)

0

En el anterior post traté las acciones habituales que realizamos con Cassandra: guardar, actualizar y eliminar. Sin embargo aun quedan dos acciones muy útiles por tratar: los contadores y los indices secundarios.

 

CONTADORES

Los contadores son en realidad un tipo especial de validador de Column Family.

 

CREAR UN CONTADOR 

Para crearla procedemos de la siguiente manera:

– Accedemos a Cassandra Cluster Admin:

Página principal de Cassandra Cluster Admin

– Entramos en el keyspace con el que estamos trabajando:

Detalle del keyspace my_keyspace

– Pulsamos en Create New Column Family y escribimos los siguientes datos:

Datos para crear una Column Family con contadores

– En Default Validation Class el texto completo a escribir es:

org.apache.cassandra.db.marshal.CounterColumnType

– Y pulsamos el botón Create Column Family.

Varias cosas sobre los CounterColumn:
– Para crear los CounterColumns es obligatorio indicar en Default Validation Class la clase de validador correcto. Indicado más arriba.
– Los contadores puedes tener números positivos o negativos.
– Los CounterColumns no son un sustituto de el autoincrement de las bases relacionales.

Ahora que ya está creada la Column Family es hora de programar.

 

GUARDAR Y/O ACTUALIZAR UN CONTADOR 

En nuestra clase en cassandra.php creamos el siguiente método:

 

  1. <?php
  2.  
  3. public function guardarContador($name_columnFamily, $key, $column, $value=1, $super_column=NULL){
  4.  
  5. try {
  6. if (!is_null($super_column)){
  7. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  8. $column_family->add($key, $super_column, $column, $value);
  9. }
  10. else{
  11. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  12. $column_family->add($key, $column, $value);
  13. }
  14. return true;
  15. }
  16. catch(Exception $e){
  17. return false;
  18. }
  19. }

 

Con este método podremos incrementar o disminuir el contador.


$name_columnFamily
: Es el nombre de la column family donde se encuentra el contador a modificar.

$key: Clave del registro donde se encuentra el contador.
$column: Nombre del contador.
$value: Valor a añadir al contador.
$super_column: Clave de la super column donde se encuentra el contador.

Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', 1)){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Como ves, para recuperar un contador se utiliza el mismo método que para obtener cualquier otro registro. El resultado de este código sería:

El contador se ha actualizado correctamente
 Array ( [num_total_post] => 1 )

 

PONER A CERO EL CONTADOR

Para poner a cero un contador hay que restarle el valor que tenga en ese momento el contador. En test.php escribiríamos lo siguiente:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', ($result['num_total_post']*-1))){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Y el resultado:

El contador se ha actualizado correctamente
 Array ( [num_total_post] => 0 )

 

INDICES SECUNDARIOS

Los indices secundarios son un objeto especial en Cassandra que nos permite realizar búsquedas por columnas concretas.

Estos índices solo funcionan en las column family standard, con lo que su uso se ve bastante limitado.

 

 

CREAR UN INDICE SECUNDARIO

Para ello vamos a nuestro Cassandra Cluster Admin y en la column family my_column_family_standard pulsamos en Create Secondary Index:

Detalle de la ubicación del botón Create Secondary Index

Detalle de la ubicación del botón Create Secondary Index

– Nos aparecerá el siguiente formulario:

Detalle del formulario para crear un índice secundario

Detalle del formulario para crear un índice secundario

– Para nuestro cometido vamos a crear el siguiente índice secundario:

Formulario con los datos para el ejemplo

Formulario con los datos para el ejemplo

–  Pulsamos en Add Secondary Index.

 

REALIZAR UNA CONSULTA CON UN INDICE SECUNDARIO 

Nos vamos a nuestro archivo cassandra.php y añadimos el siguiente método:

  1. <?php
  2.  
  3. private function getIndexOperator($value){
  4. switch ($value){
  5. case '=':
  6. $operator = 'EQ';
  7. break;
  8. case '>=':
  9. $operator = 'GTE';
  10. break;
  11. case '>':
  12. $operator = 'GT';
  13. break;
  14. case '<=':
  15. $operator = 'LTE';
  16. break;
  17. case '<':
  18. $operator = 'LT';
  19. break;
  20. default:
  21. $operator = 'EQ';
  22. break;
  23. }
  24.  
  25. return $operator;
  26. }

Este método nos permitirá trabajar con operadores diferentes a la igualdad, pudiendo utilizar >,<,>=,<=.

Pero para poder trabajar con índices es necesario incluir en nuestro listado de namespaces dos nuevas clases, tal y como se muestra en el siguiente código:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\SuperColumnFamily;
  6. use phpcassa\ColumnSlice;
  7. use phpcassa\SystemManager;
  8. use phpcassa\Schema\StrategyClass;
  9. use phpcassa\Index\IndexExpression;
  10. use phpcassa\Index\IndexClause;

A continuación creamos el método que generará la consulta con los índices secundarios.

 

  1. <?php
  2.  
  3. public function obtenerPorIndices($name_columnFamily, $arrayColumnsValues, $range_start = "", $range_end = '', $column_count = 100, $invertir_orden = false){
  4.  
  5. try{
  6. // Creamos el objeto
  7. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  8.  
  9. // Inicializamos las variables
  10. $index_exp = array();
  11. $registros = array();
  12.  
  13. // Creamos un array de index_expression
  14. foreach($arrayColumnsValues as $key => $value){
  15. if (array_key_exists('operator', $value)){
  16. $op = $this->getIndexOperator($value['operator']);
  17. }
  18. else{
  19. $this->getIndexOperator('=');
  20. }
  21.  
  22. $column = $value['values'];
  23. $key_column = key($column);
  24.  
  25. $index_exp[] = new IndexExpression($key_column, $column[$key_column], $op);
  26. }
  27.  
  28. // Creamos la index_clause
  29. $index_clause = new IndexClause($index_exp, $range_start, $column_count);
  30.  
  31. // Creamos la column_slice
  32. $column_slice = new ColumnSlice($range_start, $range_end, $column_count, $invertir_orden);
  33.  
  34. // Recuperamos los registros
  35. $rows = $column_family->get_indexed_slices($index_clause, $column_slice);
  36.  
  37. foreach($rows as $key => $columns){
  38. if (!array_key_exists($key, $registros)){ $registros[$key] = null; }
  39. $registros[$key] = $columns;
  40. }
  41. return $registros;
  42. }catch (Exception $e){
  43. return false;
  44. }
  45. }

 

Con este método podremos buscar registros con varios índices secundarios.

Lo primero que hacemos en este método es crear el objeto ColumnFamily que nos proveerá de los métodos para hacer la consulta con indices secundarios. A continuación inicializamos varias variables necesarias para el método.

Dentro de un bucle creamos un array de IndexExpression(). Este objeto le indicará a Cassandra qué indices, con qué valores y qué operador se deben buscar los registros.

Seguidamente creamos la iIndexClause(), que nos permite indicarle la key desde la que comenzará a recuperar registros y el número de registros a obtener.

Por último recuperamos los registros utilizando el método get_indexed_slices().

Para probar el método vamos a crear datos de prueba en test.php y haremos la consulta:

 

  1. <?php
  2.  
  3. $data[] = array(
  4. 'title' => 'Apache Cassandra',
  5. 'license' => 'Open Source',
  6. 'category' => 'no-sql',
  7. );
  8.  
  9. $data[] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql',
  13. );
  14.  
  15. $data[] = array(
  16. 'title' => 'MySQL',
  17. 'license' => 'Open Source',
  18. 'category' => 'sql',
  19. );
  20.  
  21. foreach($data as $key => $value){
  22. $cass->guardar('my_column_family_standard', $key, $value);
  23. }
  24.  
  25. $arrayColumnsValues[] = array(
  26. 'values' => array(
  27. 'category' => 'no-sql'
  28. ),
  29. 'operator' => '='
  30. );
  31.  
  32. $result = $cass->obtenerPorIndices('my_column_family_standard', $arrayColumnsValues);
  33.  
  34. print_r($result);

 

Si ejecutamos el código anterior Cassandra nos devolverá:

Array ( [0] => Array ( [title] => Apache Cassandra [license] => Open Source [category] => no-sql ) [1] => Array ( [title] => MongoDB [license] => Open Source [category] => no-sql ) )

[ci-box type=”warning”]Al utilizar un operador diferente al = puede que Cassandra te devuelva un error. Para evitarlo añade otro indice secundario a la consulta pero con el operador =, siendo este la primera columna que Cassandra procese. Por alguna razón Cassandra devuelve un error si no se hace así. [/ci-box]

Con este post concluye la parte básica de PHPCassa, Cassandra y Cassandra Cluster Admin. En el próximo post y siguientes trataré varios temas que se han quedado un poco colgados o faltan por explicar como ordenar registros, cómo crear claves, mejorar el rendimiento de Cassandra, crear clusters, etc.

 

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: Cassandra Cluster Admin, el phpMyAdmin de Cassandra

3

En el anterior post expliqué el funcionamiento de la consola de Cassandra y como trabajar con ella. En este post explicaré como hacer lo mismo de una forma más rápida y fácil.

La razón de que no haya empezado ha explicar como se utiliza Cassandra desde PHP, es que primero hay que conocer cómo funciona Cassandra, su modelo de datos (que ya hemos visto) y algunos comandos básicos para ir aprendiendo a guardar y recuperar datos. El próximo post ya trataré el funcionamiento de PHPCassa y empezaremos a programar.

Este post será bastante ligerito. Explicaré principalmente como hacer lo mismo que hicimos por consola pero de modo gráfico. CassAdmin, como yo le llamo, tiene más opciones de edición para los keyspaces y column families de los que vamos a ver (igual que ocurría con la consola), pero solo tocaremos las opciones más habituales.

 

INSTALACIÓN

Lo típico en estos casos. Descargar. Descomprimir y ejecutar. Descargamos los archivos desde el repositorio de git: https://github.com/sebgiroux/Cassandra-Cluster-Admin, o a través de git o como archivo comprimido. Como más te guste.

Proceso para descargar Cassandra Cluster Admin

Página de descargas del administrador

Ahora descomprimimos a una carpeta dentro de nuestro servidor web, ya que trabajamos con una aplicación programada en PHP.

Si tienes Cassandra instalado en otro equipo que no sea en local, una máquina virtual por ejemplo, tendrás que cambiar la ip a la que se conecta cassAdmin. Es bastante sencillo. Para ello debes modificar el archivo includes/config.inc.php y sustituir la ip de localhost (127.0.0.1)  por la ip del equipo en el que tengas instalado Cassandra:

Archivo config.inc.php

Como verás en la captura, yo utilizo la ip local 192.168.1.10 que pertenece a una máquina virtual. Si tuviera instalado Cassandra en  el mismo equipo la ip a la que debería apuntar sería 127.0.0.1. El puerto no lo modificamos.

Una vez instalado y configurado (si fuese el caso) probamos a acceder desde nuestro navegador. Debería mostrarte algo como esto:

Página principal de Cassandra Cluster Admin

CREAR KEYSPACES

Como has podido ver, en la página principal del administrador ya aparece un keyspace, llamado system, perteneciente a Cassandra, con lo que lo mantendremos como está.

Justo encima tenemos un botón para crear un nuevo keyspace (Create a new keyspace). Lo pulsamos.

Formulario para crear un keyspace

Solo nos pide tres parámetros a rellenar:


Keyspace name
: El nombre del keyspace a crear.
Replication factor: Es el número de servidores o instancias de Cassandra de los que se debe guardar un registro u obtener una respuesta al recuperar algún registro.
Strategy: Es la estrategia que seguirá Cassandra para guardar los datos. En el caso de tener varios servidores o centro de datos diferenciados entre sí, se aplicará una estrategia u otra para que los datos no se pierdan. Más info: http://answers.oreilly.com/topic/2408-replica-placement-strategies-when-using-cassandra/ 

En nuestro caso escribiremos los siguientes valores:

Formulario para crear un keyspace con datos

Pulsamos en Create keyspace y nos llevará a la página principal:

Página principal mostrando el keyspace que acabamos de crear

Pulsamos sobre el keyspace que acabamos de crear y nos llevará a la siguiente página:

Página de detalle del keyspace my_keyspace

Aquí podemos ver información relativa al keyspace y al anillo (o cluster) en el que se encuentra guardado. También nos permite editar el keyspace o eliminarlo, pero la opción más interesante es la de crear nuevas column families (Create a new column family).

 

CREAR UNA COLUMN FAMILY

Dentro del keyspace pulsamos sobre el botón Create a new column family, nos mostrará lo siguiente:

Formulario para crear una column family

 

Primero crearemos una column family standard con los siguientes datos:

Datos para crear la primera column family

Para crear una column family solo son necesarios tres parámetros:


Column Family Name
: El nombre de la column family que vamos a crear.
Column Type: El tipo de column family que vamos a crear (Standard o Super).
Comparator Type: El comparador principal de las columnas. Es decir, la codificación que tendrán los datos dentro de la column family.

Pulsamos en Create Column Family y en la página de nuestro keyspace se habrá añadido una nueva column family:

Detalle de la column family creada

 

AÑADIR REGISTROS A UNA COLUMN FAMILY STANDARD

Ahora toca guardar registros en la BD.
Como comenté en post anteriores Cassandra no necesita conocer los campos de las tablas (nuestras column families) ya que los creamos cada vez que añadimos un registro.

Primero en la página principal del keyspace haz click en el nombre de la column family. Te aparecerá lo siguiente:

 

Detalle de la página principal de la column family creada

En esta página te aparecerá, además de la información referente a la column family, los siguientes botones:


Browse Data
: Para mostrar un listado de los registros que contiene la column family.
Create Secondary Index: Para crear indices secundarios. Parecido a los indices de MySQL.
Get Key: Para buscar una clave o registro concreto.
Insert Row: Para insertar un nuevo registro.
Edit Column Family: Para editar los parámetros de la column family.
Truncate Column Family: Para eliminar los registros de la column family sin eliminar esta.
Drop Column Family: Para eliminar la column family y su contenido.

Pulsamos en Insert Row. Nos aparecerá lo siguiente:

Formulario para insertar registros

Siempre que añadamos un nuevo registro deberemos indicar una key diferente que deberá ser única, sino cassAdmin pensará que lo que quieres hacer es actualizar ese registro. Añadimos los siguientes datos al formulario:

Formulario para insertar registros con datos

 

Para añadir otra fila de cuadro de texto solo tienes que pulsar el botón Add…
Volvemos a la página principal de la column family y pulsamos en Browse Data. Aquí veremos un listado con los registros que hayamos añadido:

 

Listado de registros

 

CREAR UNA COLUMN FAMILY SUPER Y AÑADIR REGISTROS

El proceso para crear una column family Super es idéntico a las column family Standard, solo hay que cambiar un valor a la hora de crearla:

Creación de una column family Super

Entramos en la página principal de la nueva column family y pulsamos en Insert Row. Aquí veremos que el formulario a cambiado un poco, nos aparece un nuevo campo llamado Super Column Name y un nuevo botón encima del formulario, Add Super Column:

Formulario para insertar registros de una column family super

Las column family Super son como las muñecas matrioskas, esas figuras que si las abrías había otra igual dentro, y dentro de esa otra más, y otra, etc. Algo parecido sucede con estas column family. Disponemos de una key (nuestra primera matrioska) que contiene a las super columns (segunda matrioska), que a su vez contienen las columnas clave:valor.

Añadamos un registro para verlo:

Datos para crear una super column

Si nos vamos a Browse Data:

Listado de registros en una column family Super

Como ves, ahora las columns se agruparían dentro de la super column. Añadiré más registros para que lo veas mejor:

Listado de registros en una column family Super

¿Ves? Las keys agrupan a las super columns y estas a su vez a las columns.

 

Creo que esto es suficiente para que conozcas el funcionamiento de Cassandra Cluster Admin. Quedarían algunas cosillas, como editar registros, hacer búsquedas o eliminar registros, pero eso es bastante sencillo (a excepción de las Secondary Index y las Counter Columns que trataré más adelante).

Para cualquier duda o problema déjala en los comentarios.

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: El modelo de datos

5

Si has trabajado con una base de datos relacional tal vez te resulte algo confuso al principio comprender el modelo de datos que usa Cassandra, intentaré ser lo más claro posible, pero si te surgen preguntas no dudes en dejarlas en los comentarios.

 

Columnas

El elemento más básico de la base de datos Cassandra es la columna, se compone de tres elementos: nombre de la columna, valor y timestamp. Os muestro un ejemplo como un array:

array(
  "nombre" => "email",
  "valor" => "webmaster@localhost.com",
  "timestamp" => time(),
);

 

Super columnas

Es el conjunto de columnas con sus correspondientes valores:

array(
  "nombre_superColumna" => array(
    "usuario1" => array(
      "nombre" => "email",
      "valor" => "webmaster@localhost.com",
      "timestamp" => time()
    ),
    "usuario2" => array(
      "nombre" => "email",
      "valor" => "email@email.com",
      "timestamp" => time()
    ),
    "usuario3" => array(
      "nombre" => "email",
      "valor" => "otroemail@otroemail.com",
      "timestamp" => time()
    ),
  ),
)

 

Familia de columnas

Es el conjunto de columnas o super columnas. Me explico:

Las column Family o  familia de columnas se puede configurar de dos maneras: como Super o como Standard. Si se elige la opción Standard, en la column family solo se podrán guardar columnas no super columnas. En cambio si la column family está configurada como Super podrá guardar, además de las columnas, las super columnas. Esta flexibilidad permite jugar con la base de datos y adaptarla a nuestras necesidades.

Ejemplo:

array(
  "name" => "ColumnFamily",
  array( "name" => "SuperColumn",
    array( "colums" )
  ),
)

Keyspace

El keyspace es nuestra base de datos, donde alojaremos todas las columFamilies que necesitemos.

Ejemplo:

array(
  "name" => "keyspace",
  array("name" => "columnFamily",
    array(
      [...]
    ),
  ),
)
Logo Cassandra

Cassandra y PHP para desarrolladores SQL: phpCassa (III)

0

Ya he tratado casi en su totalidad las funciones más básicas de phpCassa y Cassandra, con lo que ya tendrás un conocimiento suficientemente amplio de lo que se puede hacer con phpCassa y Cassandra, el resto dependerá de la evolución de la BD y de las librerías (y de la experiencia que tengas xP).

Hoy trataré varios temas que por las consultas realizadas por varios usuarios se merece un post aparte en el que se pueda tratar de una forma más amplia. Estos temas son: ordenar registros, crear keys para los registros y contar registros.

 

ORDENAR REGISTROS

Cassandra dispone de varios tipos de comparadores y subcomparadores para ordenar los registros. El más habitual es UTF-8 pero hay varios más. Si vamos a Cassandra Cluster Admin y accedemos al formulario de creación de columns family, podremos pasar el ratón por los interrogantes que hay a la izquierda de los campos para poder ver los diferentes tipos de comparadores:

Tipos de comparadores

Tipos de comparadores

Como puedes ver, estos comparadores le dicen a Cassandra como ordenar los registros. Si has seguido este tutorial ya conocerás al menos uno de los comparadores (utf-8) por tanto vamos a ver como ordena Cassandra los registros con este comparador.

Para este primer ejemplo vamos a crear una column family llamada column_family_order_utf8 de tipo standard y el tipo de comparador UTF8Type.

Vamos a nuestro archivo test.php y escribimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. foreach($data as $key => $value){
  31. $cass->guardar('column_family_order_utf8', $key, $value);
  32. }

Este código guardará un array desordenado en nuestra column family. Una vez ejecutado el script accedemos a Cassandra Cluster Admin y visualizamos los registros de column_family_order_utf8, nos mostrará el siguiente resultado:

Listado de los registros guardados

Listado de los registros guardados

Como puedes observar los registros no se han ordenado, sin embargo cada una de las columns de cada registro sí están ordenadas por orden alfabético. Esto sucede porque los comparadores no ordenan por keys o claves de los registros sino por columns, aunque hay un caso especial, si la column family es super los registros si estarán ordenados. Veamoslo.

Creamos una column family llamada column_family_utf8_super con el tipo de comparador UTF8Type y el tipo de column family como super. En nuestro archivo test.php añadimos el siguiente código:

  1. <?php
  2.  
  3. $data = array();
  4. $data[5] = array(
  5. 'title' => 'Apache Cassandra',
  6. 'license' => 'Open Source',
  7. 'category' => 'no-sql',
  8. );
  9. $data[3] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql'
  13. );
  14. $data[1] = array(
  15. 'title' => 'Neo4j',
  16. 'license' => 'Open Source',
  17. 'category' => 'no-sql',
  18. );
  19. $data[4] = array(
  20. 'title' => 'MySQL',
  21. 'license' => 'Open Source',
  22. 'category' => 'sql'
  23. );
  24. $data[2] = array(
  25. 'title' => 'MariaDB',
  26. 'license' => 'Open Source',
  27. 'category' => 'sql',
  28. );
  29.  
  30. $cass->guardar('column_family_order_utf8_super', 'databases', $data);

Una vez ejecutado este script nos vamos a nuestra column family y nos mostrará lo siguiente:

Listado de registros en la column family

Listado de registros en la column family

Como puedes observar ahora sí están ordenados los registros, pero claro ahora están dentro de una super column.

En Cassandra la ordenación se realiza a las columnas del registro o los registros dentro de las super columns, si creasemos otra super column, esta no se ordenaría con respecto a la ya creada, ‘databases’.

Aunque esta ordenación puede ser útil y totalmente funcional, para los desarrolladores que vengan de las bases de datos relacionales les puede resultar confuso. Por ejemplo, para guardar los comentarios de un post de un blog podríamos utilizar este tipo de ordenación perfectamente, ya que podemos utilizar el id del post como key de la super column (el ‘databases’ de la imagen anterior se sustituiría por el id del post) y el timestamp (como este 1337787675.32246500) para la key de los registros. De esta forma tendríamos ordenados los comentarios por tiempo y por post. Si quisieramos recuperar los comentarios de un post concreto solo tendríamos que pasarle al método correspondiente el id del post como key de la super column.

¿Y si quisieramos guardar los post del blog? En este caso una column family super nos lo podría resolver indicando como key de la super columnposts‘  y utilizando como key en los registros el timestamp. Pero si quisieramos hacer busquedas utilizando indices secundarios una column family super no nos valdría, ya que los indices secundarios no funcionan en ellas.

Para ello habría que crear una column family standard para los post, que nos permitirá usar los indices secundarios, y una column family super para guardar las keys de los post dentro de una super column con key, por ejemplo, ‘key_posts‘. Para hacer la consulta habría que recuperar las keys de los posts a mostrar en primer lugar, y después, utilizando un método de phpCassa que aun no hemos usado recuperar los registros correspondientes a esas keys.

El método que deberíamos añadir a nuestro archivo cassandra.php sería el siguiente:

  1. <?php
  2.  
  3. function obtenerMultiplesRegistros($columnFamily, $multiKeys){
  4.  
  5. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  6.  
  7. $result = $column_family->multiget($multiKeys);
  8.  
  9. return $result;
  10.  
  11. }

A este método le pasamos el nombre de la column family standard donde hemos guardado los posts y un array con las keys a recuperar, nos devolverá un array con los datos de cada uno de los posts que le hemos pedido… y en el orden en el que le hayamos pasado las keys a recuperar.

Existe otra forma de ordenar registros, pero además de que en versiones posteriores de Cassandra desaparecerá y provoca problemas de rendimiento, yo no la recomiendo, ya que pierdes todos los beneficios que ofrece Cassandra. Aun así os dejo un link para que le echéis un ojo xD:

http://ria101.wordpress.com/2010/02/22/cassandra-randompartitioner-vs-orderpreservingpartitioner/

Y os dejo otro link para que tengais algo más de información respecto a ordenar registros en Cassandra:

http://ayogo.com/blog/2010/04/09/sorting-in-cassandra/

 

CREAR CLAVES O KEYS PARA LOS REGISTROS

Como has podido ver en el apartado anterior, para ordenar los registros es muy importante tener una key de cada registro que sea única y siempre vaya en orden. Esto las bases de datos relacionales nos lo dan ya hecho, sin embargo en las bases de datos no-sql esto no es así.

Las bases de datos no-sql se crearon para optimizar la lectura y escritura de los registros en la base de datos, esto provocó que algunas funcionalidades muy útiles en las bases relaciones no tuvieran cabida en las no-sql. Por tanto para mantener en orden los registros debemos crear nosotros nuestras propias claves.

phpCassa dispone de un método para crear una clave aleatoria basada en el timestamp, para utilizarla crearemos un nuevo método en nuestro archivo cassamdra.php que devolverá la clave:

  1. <?php
  2.  
  3. public function obtenerUuid(){
  4.  
  5. $util = new CassandraUtil();
  6.  
  7. return $util->import($util->uuid1());
  8. }

Como me está quedando un post muy largo os lo voy a dejar como deberes xD. Sería interesante probarlo tanto con column families standard y super, además de con un tipo de comparador UTF8Type y TimeUUIDType.

Como el chorro de letras y números que devuelve es muy poco legible yo suelo utilizar mi propio sistema de claves, normalmente utilizo el microtime() de php y un par de ids de lo que se esté guardando: el id del usuario, el id de lo que se ha creado, etc. Algo que lo diferencie del resto. Para la clave primero pongo los segundos que devuelve microtime() y después los microsegundos. Para que os hagais una idea sería algo así:

$key = $segundos . ‘.’ . $microsegundos . ‘_’ . $id_post . ‘_’ . $id_usuario;

De esta forma le estamos dando una clave para los ejemplos del anterior apartado, más concretamente para los comentarios en un post.

 

CONTAR REGISTROS

El último apartado de este post. Contar registros. Esto es algo que Cassandra no lleva muy bien, sobre todo con grandes cantidades de información.

Cassandra cuando recibe una petición de lectura/escritura utiliza unas tablas en memoria llamadas memtables (el que le puso el nombre de rompió la cabeza pensando). Cuantas más peticiones reciba Cassandra más memtables creará, de esta forma permitirá una cierta consistencia de la información almacenada en la base de datos.

Cuando le pedimos a phpCassa que nos devuelva el número de registros en una column family o en una super column concreta, lo que está haciendo en realidad es hacer una petición a Cassandra de todos los registros que haya en la column family o en la super column. Cuando esto ocurre Cassandra guardará estos registros en la RAM del servidor antes de enviarlos a phpCassa, y sí Cassandra no cuenta los registros, porque no está pensada para eso, es phpCassa la que cuenta los registros y te devuelve el número concreto.

El método que utiliza phpCassa para contar registros es el que os muestro a continuación, dentro de un método para añadir al archivo cassandra.php:

  1. <?php
  2.  
  3. public function contar_registros($columnFamily, $key){
  4.  
  5. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  6.  
  7. return $column_family->get_count($key);
  8.  
  9. }

Esta forma de contar registros provoca que Cassandra consuma todos los recursos de RAM del servidor, con lo que no os la recomiendo.

La mejor manera de contar registros con Cassandra es utilizar una column family con contadores, de tal forma que en nuestro código cada vez que se guarde un registro en la bd se aumente el contador que lleva la cuenta de los registros guardados. En el caso de que se eliminen, habría que disminuirlo. Y en el caso de que el registro se esté actualizando controlar que no aumente el contador xD.

Cualquier duda que tengais intentaré responderla lo mejor posible en los comentarios.

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: phpCassa (II)

0

En el anterior post traté las acciones habituales que realizamos con Cassandra: guardar, actualizar y eliminar. Sin embargo aun quedan dos acciones muy útiles por tratar: los contadores y los indices secundarios.

 

CONTADORES

Los contadores son en realidad un tipo especial de validador de Column Family.

 

CREAR UN CONTADOR 

Para crearla procedemos de la siguiente manera:

– Accedemos a Cassandra Cluster Admin:

Página principal de Cassandra Cluster Admin

– Entramos en el keyspace con el que estamos trabajando:

Detalle del keyspace my_keyspace

– Pulsamos en Create New Column Family y escribimos los siguientes datos:

Datos para crear una Column Family con contadores

– En Default Validation Class el texto completo a escribir es:

org.apache.cassandra.db.marshal.CounterColumnType

– Y pulsamos el botón Create Column Family.

Varias cosas sobre los CounterColumn:
– Para crear los CounterColumns es obligatorio indicar en Default Validation Class la clase de validador correcto. Indicado más arriba.
– Los contadores puedes tener números positivos o negativos.
– Los CounterColumns no son un sustituto de el autoincrement de las bases relacionales.

Ahora que ya está creada la Column Family es hora de programar.

 

GUARDAR Y/O ACTUALIZAR UN CONTADOR 

En nuestra clase en cassandra.php creamos el siguiente método:

  1. <?php
  2.  
  3. public function guardarContador($columnFamily, $key, $column, $value=1, $super_column=NULL){
  4.  
  5. try {
  6. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  7. $column_family->add($row_key, $column, $value, $super_column);
  8. return true;
  9. }
  10. catch(Exception $e){
  11. return false;
  12. }
  13. }

Con este método podremos incrementar o disminuir el contador.


$columnFamily
: Es el nombre de la column family donde se encuentra el contador a modificar.

$key: Clave del registro donde se encuentra el contador.
$column: Nombre del contador.
$value: Valor a añadir al contador.
$super_column: Nombre de la super column donde se encuentra el contador.

Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', 1)){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Como ves, para recuperar un contador se utiliza el mismo método que para obtener cualquier otro registro. El resultado de este código sería:

El contador se ha actualizado correctamente
Array ( [num_total_post] => 1 )

 

PONER A CERO EL CONTADOR

Para poner a cero un contador hay que restarle el valor que tenga en ese momento el contador. En test.php escribiríamos lo siguiente:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', ($result['num_total_post']*-1))){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Y el resultado:

El contador se ha actualizado correctamente
Array ( [num_total_post] => 0 )

 

INDICES SECUNDARIOS

Los indices secundarios son un objeto especial en Cassandra que nos permite realizar búsquedas por columnas concretas.

Estos índices solo funcionan en las column family standard, con lo que su uso se ve bastante limitado.

 

 

CREAR UN INDICE SECUNDARIO

Para ello vamos a nuestro Cassandra Cluster Admin y en la column family my_column_family_standard pulsamos en Create Secondary Index:

Detalle de la ubicación del botón Create Secondary Index

Detalle de la ubicación del botón Create Secondary Index

– Nos aparecerá el siguiente formulario:

Detalle del formulario para crear un índice secundario

Detalle del formulario para crear un índice secundario

– Para nuestro cometido vamos a crear el siguiente índice secundario:

Formulario con los datos para el ejemplo

Formulario con los datos para el ejemplo

–  Pulsamos en Add Secondary Index.

 

REALIZAR UNA CONSULTA CON UN INDICE SECUNDARIO 

Nos vamos a nuestro archivo cassandra.php y añadimos el siguiente método:

  1. <?php
  2.  
  3. public function obtenerPorIndices($columnFamily, $arrayColumnsValues, $rangeStart = "", $columnCount = 100, $ordenar = true){
  4.  
  5. try{
  6. // Creamos el objeto
  7. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  8.  
  9. // Inicializamos las variables
  10. $index_exp = array();
  11. $registros = array();
  12.  
  13. // Creamos un array de index_expression
  14. foreach($arrayColumnsValues as $key => $value){
  15. $index_exp[] = CassandraUtil::create_index_expression($key, $value);
  16. }
  17.  
  18. // Creamos la index_clause
  19. $index_clause = CassandraUtil::create_index_clause($index_exp, $rangeStart, $columnCount);
  20.  
  21. // Recuperamos los registros
  22. $rows = $column_family->get_indexed_slices($index_clause, NULL, $rangeStart, '', $ordenar, $columnCount);
  23.  
  24. return $rows;
  25. }catch (Exception $e){
  26. return false;
  27. }
  28. }

Con este método podremos buscar registros con varios índices secundarios.

Lo primero que hacemos en este método es crear el objeto ColumnFamily que nos proveerá de los métodos para hacer la consulta con indices secundarios. A continuación inicializamos varias variables necesarias para el método.

Dentro de un bucle creamos un array de index_expression(). Este objeto le indicará a Cassandra qué indices y con qué valores se deben buscar los registros.

Seguidamente creamos la index_clause(), que nos permite indicarle la key desde la que comenzará a recuperar registros y el número de registros a obtener.

Por último recuperamos los registros utilizando el método get_indexed_slices().

Para probar el método vamos a crear datos de prueba en test.php y haremos la consulta:

  1. <?php
  2.  
  3. $data[] = array(
  4. 'title' => 'Apache Cassandra',
  5. 'license' => 'Open Source',
  6. 'category' => 'no-sql',
  7. );
  8.  
  9. $data[] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql',
  13. );
  14.  
  15. $data[] = array(
  16. 'title' => 'MySQL',
  17. 'license' => 'Open Source',
  18. 'category' => 'sql',
  19. );
  20.  
  21. foreach($data as $key => $value){
  22. $cass->guardar('my_column_family_standard', $key, $value);
  23. }
  24.  
  25. $arrayColumnsValues = array(
  26. 'category' => 'no-sql',
  27. );
  28.  
  29. $result = $cass->obtenerPorIndices('my_column_family_standard', $arrayColumnsValues);
  30.  
  31. print_r($result);

Si ejecutamos el código anterior Cassandra nos devolverá:

Array ( [0] => Array ( [title] => Apache Cassandra [license] => Open Source [category] => no-sql ) [1] => Array ( [title] => MongoDB [license] => Open Source [category] => no-sql ) )

Con este post concluye la parte básica de phpCassa, Cassandra y Cassandra Cluster Admin. En el próximo post y siguientes trataré varios temas que se han quedado un poco colgados o faltan por explicar como ordenar registros, cómo crear claves, mejorar el rendimiento de Cassandra, crear clusters, etc.

 

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: Cassandra Cluster Admin, el phpMyAdmin de Cassandra

4

En el anterior post expliqué el funcionamiento de la consola de Cassandra y como trabajar con ella. En este post explicaré como hacer lo mismo de una forma más rápida y fácil.

La razón de que no haya empezado ha explicar como se utiliza Cassandra desde PHP, es que primero hay que conocer cómo funciona Cassandra, su modelo de datos (que ya hemos visto) y algunos comandos básicos para ir aprendiendo a guardar y recuperar datos. El próximo post ya trataré el funcionamiento de phpCassa y empezaremos a programar.

Este post será bastante ligerito. Explicaré principalmente como hacer lo mismo que hicimos por consola pero de modo gráfico. CassAdmin, como yo le llamo, tiene más opciones de edición para los keyspaces y column families de los que vamos a ver (igual que ocurría con la consola), pero solo tocaremos las opciones más habituales.

 

INSTALACIÓN

Lo típico en estos casos. Descargar. Descomprimir y ejecutar. Descargamos los archivos desde el repositorio de git: https://github.com/sebgiroux/Cassandra-Cluster-Admin, o a través de git o como archivo comprimido. Como más te guste.

Repositorio de Cassandra Cluster Admin

Página de descargas del administrador

Ahora descomprimimos a una carpeta dentro de nuestro servidor web, ya que trabajamos con una aplicación programada en PHP.

Si tienes Cassandra instalado en otro equipo que no sea en local, una máquina virtual por ejemplo, tendrás que cambiar la ip a la que se conecta cassAdmin. Es bastante sencillo. Para ello debes modificar el archivo includes/config.inc.php y sustituir la ip de localhost (127.0.0.1)  por la ip del equipo en el que tengas instalado Cassandra:

Archivo config.inc.php

Como verás en la captura, yo utilizo la ip local 192.168.1.10 que pertenece a una máquina virtual. Si tuviera instalado Cassandra en  el mismo equipo la ip a la que debería apuntar sería 127.0.0.1. El puerto no lo modificamos.

Una vez instalado y configurado (si fuese el caso) probamos a acceder desde nuestro navegador. Debería mostrarte algo como esto:

Página principal de Cassandra Cluster Admin

CREAR KEYSPACES

Como has podido ver, en la página principal del administrador ya aparece un keyspace, llamado system, perteneciente a Cassandra, con lo que lo mantendremos como está.

Justo encima tenemos un botón para crear un nuevo keyspace (Create a new keyspace). Lo pulsamos.

Formulario para crear un keyspace

Solo nos pide tres parámetros a rellenar:


Keyspace name
: El nombre del keyspace a crear.
Replication factor: Es el número de servidores o instancias de Cassandra de los que se debe guardar un registro u obtener una respuesta al recuperar algún registro.
Strategy: Es la estrategia que seguirá Cassandra para guardar los datos. En el caso de tener varios servidores o centro de datos diferenciados entre sí, se aplicará una estrategia u otra para que los datos no se pierdan. Más info: http://answers.oreilly.com/topic/2408-replica-placement-strategies-when-using-cassandra/ 

En nuestro caso escribiremos los siguientes valores:

Formulario para crear un keyspace con datos

Pulsamos en Create keyspace y nos llevará a la página principal:

Página principal mostrando el keyspace que acabamos de crear

Pulsamos sobre el keyspace que acabamos de crear y nos llevará a la siguiente página:

Página de detalle del keyspace my_keyspace

Aquí podemos ver información relativa al keyspace y al anillo (o cluster) en el que se encuentra guardado. También nos permite editar el keyspace o eliminarlo, pero la opción más interesante es la de crear nuevas column families (Create a new column family).

 

CREAR UNA COLUMN FAMILY

Dentro del keyspace pulsamos sobre el botón Create a new column family, nos mostrará lo siguiente:

Formulario para crear una column family

 

Primero crearemos una column family standard con los siguientes datos:

Datos para crear la primera column family

Para crear una column family solo son necesarios tres parámetros:


Column Family Name
: El nombre de la column family que vamos a crear.
Column Type: El tipo de column family que vamos a crear (Standard o Super).
Comparator Type: El comparador principal de las columnas. Es decir, la codificación que tendrán los datos dentro de la column family.

Pulsamos en Create Column Family y en la página de nuestro keyspace se habrá añadido una nueva column family:

Detalle de la column family creada

 

AÑADIR REGISTROS A UNA COLUMN FAMILY STANDARD

Ahora toca guardar registros en la BD.
Como comenté en post anteriores Cassandra no necesita conocer los campos de las tablas (nuestras column families) ya que los creamos cada vez que añadimos un registro.

Primero en la página principal del keyspace haz click en el nombre de la column family. Te aparecerá lo siguiente:

 

Detalle de la página principal de la column family creada

En esta página te aparecerá, además de la información referente a la column family, los siguientes botones:


Browse Data
: Para mostrar un listado de los registros que contiene la column family.
Create Secondary Index: Para crear indices secundarios. Parecido a los indices de MySQL.
Get Key: Para buscar una clave o registro concreto.
Insert Row: Para insertar un nuevo registro.
Edit Column Family: Para editar los parámetros de la column family.
Truncate Column Family: Para eliminar los registros de la column family sin eliminar esta.
Drop Column Family: Para eliminar la column family y su contenido.

Pulsamos en Insert Row. Nos aparecerá lo siguiente:

Formulario para insertar registros

Siempre que añadamos un nuevo registro deberemos indicar una key diferente que deberá ser única, sino cassAdmin pensará que lo que quieres hacer es actualizar ese registro. Añadimos los siguientes datos al formulario:

Formulario para insertar registros con datos

 

Para añadir otra fila de cuadro de texto solo tienes que pulsar el botón Add…
Volvemos a la página principal de la column family y pulsamos en Browse Data. Aquí veremos un listado con los registros que hayamos añadido:

 

Listado de registros

 

CREAR UNA COLUMN FAMILY SUPER Y AÑADIR REGISTROS

El proceso para crear una column family Super es idéntico a las column family Standard, solo hay que cambiar un valor a la hora de crearla:

Creación de una column family Super

Entramos en la página principal de la nueva column family y pulsamos en Insert Row. Aquí veremos que el formulario a cambiado un poco, nos aparece un nuevo campo llamado Super Column Name y un nuevo botón encima del formulario, Add Super Column:

Formulario para insertar registros de una column family super

Las column family Super son como las muñecas matrioskas, esas figuras que si las abrías había otra igual dentro, y dentro de esa otra más, y otra, etc. Algo parecido sucede con estas column family. Disponemos de una key (nuestra primera matrioska) que contiene a las super columns (segunda matrioska), que a su vez contienen las columnas clave:valor.

Añadamos un registro para verlo:

Datos para crear una super column

Si nos vamos a Browse Data:

Listado de registros en una column family Super

Como ves, ahora las columns se agruparían dentro de la super column. Añadiré más registros para que lo veas mejor:

Listado de registros en una column family Super

¿Ves? Las keys agrupan a las super columns y estas a su vez a las columns.

 

Creo que esto es suficiente para que conozcas el funcionamiento de Cassandra Cluster Admin. Quedarían algunas cosillas, como editar registros, hacer búsquedas o eliminar registros, pero eso es bastante sencillo (a excepción de las Secondary Index y las Counter Columns que trataré más adelante).

Para cualquier duda o problema déjala en los comentarios.

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: El modelo de datos

8

Si has trabajado con una base de datos relacional tal vez te resulte algo confuso al principio comprender el modelo de datos que usa Cassandra, intentaré ser lo más claro posible, pero si te surgen preguntas no dudes en dejarlas en los comentarios.

 

Columnas

El elemento más básico de la base de datos Cassandra es la columna, se compone de tres elementos: nombre de la columna, valor y timestamp. Os muestro un ejemplo como un array:

 array(
“nombre” => “email”,
“valor” => “webmaster@localhost.com”,

“timestamp” => time()

,

)

 

Super columnas

Es el conjunto de columnas con sus correspondientes valores:

array(
“nombre_superColumna” => array(

 

“usuario1” => array(
“nombre” => “email”,
“valor” => “webmaster@localhost.com”,
“timestamp” => time()
),
“usuario2” => array(
“nombre” => “email”,
“valor” => “email@email.com”,
“timestamp” => time()
),

 

“usuario3” => array(
“nombre” => “email”,
“valor” => “otroemail@otroemail.com”,
“timestamp” => time()
),

),

)

 

Familia de columnas

Es el conjunto de columnas o super columnas. Me explico:

Las column Family o  familia de columnas se puede configurar de dos maneras: como Super o como Simple. Si se elige la opción Simple, en la column family solo se podrán guardar columnas no super columnas. En cambio si la column family está configurada como Super podrá guardar, además de las columnas, las super columnas. Esta flexibilidad permite jugar con la base de datos y adaptarla a nuestras necesidades.

Ejemplo:

 array(
“name” => “ColumnFamily”,
array( “name” => “SuperColumn”,
array( “colums” )
),
)

Keyspace

El keyspace es nuestra base de datos, donde alojaremos todas las columFamilies que necesitemos.

Ejemplo:

array(
“name” => “keyspace”,
array(“name” => “columnFamily”,
array(
[…]
),
),
)

Ir arriba