Introducción a ClickHouse

0
4252

Índice de contenidos

1. Introducción

A lo largo de la historia, la información y saber utilizarla ha sido y será clave para tomar decisiones en cualquier ámbito. Todo hemos oído frases como «la información es poder», el dato cada vez está tomando mayor relevancia de la que ya tenía. Grandes compañías y no tan grandes ofrecen de forma gratuita sus servicios a cambio de nuestros datos, ¿por qué?, porque con los datos que recopilan de nosotros, leyendo nuestros mails, conociendo nuestros hábitos, nuestra salud, preferencias deportivas, etc. generan un perfil que utilizan para ofrecernos publicidad orientada, productos en los que podemos estar interesados e incluso vender dicha información a terceros.

Business Intelligence es una de las áreas especializadas en la analítica del dato, se caracteriza en transformar información en conocimiento, con el objetivo de mejorar el proceso de toma de decisiones haciendo uso de estrategias y herramientas. El volumen de la información puede llegar a millones de registros, esto hace que el uso de soluciones tradicionales no sean las más adecuadas.

Una de las estrategias más habituales en este área es OLAP (OnLine Analytical Processing) que permite agilizar la consulta de grandes cantidades de datos usando estructuras multidimensionales que contienen información resumida de otras fuentes de datos del tipo OLTP (OnLine Transaction Processing). Su uso habitual es la generación de informes para los diferentes departamentos de una empresa como pueden ser ventas, marketing, etc.

Básicamente OLAP recopila un gran volumen de información de diversas fuentes (internas o externas), las agrupa de una forma determinada para poder después explotar la información accediendo a ella mediante el uso de un lenguaje más natural, como por ejemplo: «dime el número de billetes vendidos en el último cuatrimestre por país», «rango de edades por países que acceden a la aplicación», etc…

Las características principales cuando se trabaja con escenarios OLAP son:

  • La mayoría de las peticiones son de lectura.
  • Generalmente los datos no son modificados.
  • Tablas con un gran número de columnas.
  • Las consultas procesan un gran número de filas (billones de filas por segundo) pero sólo sobre un subconjunto de columnas.
  • No son necesarias las transacciones y desde el punto de vista de consistencia del dato no es un requisito esencial.

Teniendo en cuenta como se trabaja con los datos en escenarios OLAP, herramientas tradicionales como pueden ser base de datos como MySQL, Oracle o PostgreSQL no son las más adecuadas ya que el rendimiento es bastante pobre. Son base de datos orientadas a fila, es decir, los datos son almacenados en este orden:

Fila OrderID Pagada Nombre Enviada Fecha
#0 89354350662 1 Investor Relations 1 2016-05-18 05:19:20
#1 90329509958 0 Contact us 1 2016-05-18 08:10:20
#2 89953706054 1 Mission 1 2016-05-18 07:38:00
#N

Por tanto todos los valores relativos a una fila son físicamente almacenados uno al lado del otro.

Para que los rendimientos sean realmente óptimos, generalmente, las herramientas OLAP estructuran los datos en columnas almacenándolos de esta otra forma:

Fila #0 #1 #2 #N
OrderID 89354350662 90329509958 89953706054
Pagada 1 0 1
Nombre Investor Relations Contact us Mission
Enviada 1 1 1
Fecha 2016-05-18 05:19:20 2016-05-18 08:10:20 2016-05-18 07:38:00

En estos casos los valores de diferentes columnas se almacenan por separado y los datos de la misma columna se almacenan juntos. De esta forma la recuperación se puede realizar en bloque y se puede procesar muchos más datos que con las base de datos orientadas a fila.

2. Entorno

Este tutorial está escrito usando el siguiente entorno:

  • Hardware: MacBook Pro 15’ (3,1 GHz Intel Core i7, 16GB DDR3)
  • Sistema operativo: macOS Mojave 10.14.2
  • Versiones del software:
    • Docker: 18.09.1
    • ClickHouse Server: 18.14.18
    • ClickHouse Client: 18.14.18
    • Java: 8
    • Spring Boot: 2.1.1.RELEASE

3. ClickHouse

ClickHouse es una de las muchas herramientas para trabajar con este tipo de escenarios, es un producto desarrollado por Yandex (que podemos decir que es el Google Ruso) para utilizarlo como base de su herramienta de Yandex Metrica (Live Demo) que es una aplicación similar a Google Analitics . Siendo la tercera plataforma de análisis web más utilizada del mundo por detrás de Google y Facebook.

Si echamos un vistazo a los informes de rendimiento que lo comparan con otras herramientas, ClickHouse se posiciona en una buena posición estando por encima de muchas de ellas. Os dejo unos cuantos enlaces de dichos informes:

Las características base de este producto son:

  • Una base de datos realmente orientada a columna, sin utilizar datos extras como pueden ser la longitud de una cadena de caracteres, sólo almacena los datos.
  • Los datos se comprimen reduciendo el espacio y se almacenan en disco a diferencia de otras herramientas que sólo trabajan en memoria. Esto hace que el coste por GB sea bajo.
  • Capaz de procesar en paralelo los datos exprimiendo las capacidades multicores de los servidores.
  • Los datos son procesados utilizando vectores, mejorando la eficiencia de la CPU. ClickHouse hace uso del conjunto de instrucciones SSE 4.2 que permite trabajar con estas estructuras de datos y hace que este producto sea capaz de procesar billones de registros en muy poco tiempo. Esta característica hace que sólo pueda ser desplegado en procesadores que sean compatibles con este conjunto de instrucciones.
  • Utiliza el lenguaje SQL para ejecución de las sentencias, casi idéntico al estándar SQL.
  • Permite actualizar los datos en tiempo real sin bloqueo gracias a la forma de estructurar internamente los datos.
  • Proporciona indexación por clave primaria. ClickHouse ordena fisicamente los datos en base a su clave primaria y hace posible recuperar la información almacenada para un determinado valor o un rango de valores con muy baja latencia y pocos milisegundos.
  • Capaz de ejecutar consultas en tiempo real sin necesidad de procesar los datos previamente, es decir, ClickHouse puede trabajar con millones de registros en bruto (sin realizar preprocesamientoo previo de los datos) consiguiendo ejecutar sentencias sin ninguna latencia
  • Soporte de replicación e integridad de datos.

3.1 Tipos de tablas

Como hemos comentado anteriormente, ClickHouse es una base de datos y como cualquier base de datos la información se almacena en tablas para posteriormente realizar consultas sobre ellas. La peculiaridad de esta base de datos es que dispone de un gran abanico de tipología de tablas.

En este tutorial sólo las nombraremos sin entrar en detalle. El primer tipo que podemos destacar es la familia de tablas denominadas MergeTree, podemos decir que son el núcleo y las que más usaremos para explotar nuestros datos. Las características más importantes de esta familia de tablas son:

  • tienen clave primaria y los datos están ordenados físicamente en disco. Por ejemplo, si la clave primaria es (OrderId, Date) los datos estarán ordenados por OrderId y dentro de cada OrderId estarán ordenados por Date. Además ClickHouse mantiene un indice disperso que permite encontrar los datos más rápidamente y un formato bastante ingenioso y que os recomiendo que profundicéis leyendo la documentación.
  • los datos también se dividen en particiones mediante una clave de partición similar a la clave primaria. Ésta se utiliza para crear particiones, lo que permite optimizar las consultas sólo leyendo los datos de una determinada partición. Indicar que ClickHouse creará un fichero físico independiente por cada partición creada.

A la hora de diseñar una tabla para posteriormente realizar consultas sobre ellas deberemos prestar bastante atención y elegir correctamente estas dos claves de lo contrario podremos tener problemas de rendimiento y por tanto una experiencia de usuario pobre.

Partiendo de esta característica base de esta familia luego cada tipo de tabla tiene su peculiaridad. A continuación os muestro la lista de tablas de esta familia:

  • ReplacingMergeTree: su principal característica es que elimina los datos duplicados con la misma clave primaria.
  • SummingMergeTree: une todas las filas con la misma clave primaria en una sola fila realizando un resumen de las filas compactadas.
  • AggregatingMergeTree: remplaza todas las filas con la misma clave primaria con una única fila aplicando las funciones de agregación utilizadas (ejemplo: sum, avg).
  • CollapsingMergeTree: elimina asíncronamente todas las filas que contiene los mismos campos sin tener en cuenta un campo especial llamado Sign. ClickHouse mantendrá la fila donde el valor Sign sea 1 y eliminará aquellas cuyo valor sea -1.
  • VersionedCollapsingMergeTree: tipo de tabla similar a CollapsingMergeTree pero añadiendo un campo adicional llamado Version. Incluir este nuevo campo de Version permite realizar cambios continuamente del estado de los datos sin tener que estar cambiando el estado de los anteriores guardados previamente.
  • GraphiteMergeTree: tabla diseñada para almacenar datos para Graphite.

Indicar que los procesos de compactación de cualquiera de los tipos de tablas indicados anteriormente, ClickHouse, los realiza en background y en cualquier momento sin posibilidad de planificación.

Para entrar más en detalle sobre este tipo de tablas os recomiendo leer el apartado relativo a ellas en MergeTree Family.

Por otro lado tenemos otros tipos de tablas donde la característica especial es que no soportan índices. En este caso ClickHouse nos proporciona:

  • TinyLog: son las tablas más simples destinadas a almacenar pequeños volúmenes de datos no superiores al millón de filas. Se caracteriza por almacenar cada columna en diferentes ficheros comprimidos. Se utiliza para situaciones donde se escribe una vez y luego se realizan multitud de consultas, habitualmente se utiliza para almacenar datos temporalmente que son procesados en pequeños batches. Hay que tener cuidado con este tipo de tablas ya que si se escribe y se lee al mismo tiempo las consultas retornarán un error.
  • Log: similar a TinyLog pero añadiendo un pequeño fichero llamado «marks» que almacena información para ir saltando un determinado número de filas.
  • Memory: son tablas cuyos valores se almacenan en memoria y por tanto no se realiza ningún tipo de compresión de los datos. Los datos almacenados son volátiles, es decir, si se produce un reinicio se perderán. Este tipo de tablas se utiliza habitualmente para realizar pruebas.
  • Buffer: son tablas que almacenan los datos en memoria y periódicamente las depositan en otra tabla.
  • External Data: permite cargar recursos externos como si fueran tablas para su uso en consultas.

Y por último existen otros tipos de tablas especiales:

  • Distributed: realmente no es una tabla que contenga datos sino que permite distribuir las consultas sobre aquellos servidores donde se encuentran los datos y posteriormente unificarlos y retornar el resultado de la consulta.
  • Dictionary: son como si fueran tablas maestras que se definen en la configuración de ClickHouse. Son cargados en memoria en el arranque del servidor estando disponibles para utilizarlas en las consultas.
  • Merge: no confundir con la familia de tablas MergeTree, únicamente permite unir varias tablas leyéndolas de forma paralela. Estas tablas son sólo de lectura y no están permitidas las escrituras.
  • File: son tablas creadas a partir de los valores de un fichero.
  • Null: tabla como puede ser la tabla DUAL en Oracle. Las escrituras son ignoradas y las lecturas no retornan ninguna fila.
  • URL: son tablas creadas a partir de los datos retornados de una URL.
  • View: similar a las vistas de cualquier otra base de datos.
  • MaterializedView: similar a las tablas materializadas de Oracle.
  • Kafka: permite integrarnos con este sistema de mensajes consumiendo eventos que se produzcan en él.
  • MySQL: permite almacenar en una base de datos remota de MySQL una query ejecutada sobre ClickHouse.

3.2 Interfaces de comunicación

ClickHouse ofrece dos formas de comunicarnos: mediante HTTP o por TCP utilizando su propio protocolo. Utilizando estas dos interfaces existen multitud de herramientas o drivers para acceder de forma más amigable. Yandex ofrece un cliente por línea de comandos similar al comando mysql y nos permite ejecutar cualquier tipo de consulta sobre ClickHouse. También ofrece drivers JDBC y ODBC que permite usarse con cualquier librería de acceso a datos como puede ser Spring-JDBC, MyBatis, etc..

Indicar que estas dos implementaciones hacen uso del interfaz HTTP y el rendimiento puede ser un poco menor al nativo al tener mayor sobrecarga. En el caso de que quisiéramos utilizar un driver JDBC que utilice el interfaz nativo podríamos usar una librería de terceros ClickHouse-Native-JDBC pero hay que indicar que la última versión tiene leaks de memoria y fallos en la conexión por lo que en el momento del tutorial no aconsejamos utilizarlo.

Además de las librerías o herramientas que proporciona el propio Yandex existen implementaciones de terceros como: clientes para cualquiera de los lenguajes más usado hoy día, aplicaciones visuales como puede ser Tabix, HouseOps, LightHouse, DBeaver, DataGrip, etc..

3.3 Ejemplo de uso

Una vez que hemos visto un poco las características básicas de ClickHouse vamos a realizar un ejemplo utilizando el driver JDBC de Yandex. Para el ejemplo vamos a utilizar la base de datos que proporciona Transtats sobre los vuelos de las aerolíneas desde 1987. Para nuestro ejemplo sólo cargaremos los años que van desde 2015 al 2017 que corresponde con más de 17 millones de registros y usaremos las imágenes Docker del servidor y cliente de ClickHouse que proporciona Yandex.

Lo primero es arrancar un servidor de ClickHouse, evidentemente antes debemos tener instalado Docker en nuestro sistema. Abrimos un terminal y tecleamos:

docker run -d --name some-clickhouse-server -p 8123:8123 -p 9000:9000 -p 9009:9009 --ulimit nofile=262144:262144 yandex/clickhouse-serverA continuación, arrancamos el cliente de ClickHouse y accedemos al cliente abriendo una shell para instalar los comandos wget y unzip necesarios para descargar y cargar los datos en ClickHouse:

Ya tenemos preparado nuestro entorno para cargar los datos. Lo primero nos descargamos la información de cada mes desde el 2015 al 2017:

Ahora creamos la tabla en ClickHouse donde vamos a almacenar los datos. Arrancamos un cliente de ClickHouse:

Y ejecutamos la siguiente sentencia:

Salimos del cliente ejecutando el comando «exit» y a continuación, cargamos los datos utilizando el cliente de ClickHouse:

Esto nos llevará un poco de tiempo. Una vez que el proceso de carga haya finalizado podemos realizar una prueba para ver si se han cargado los datos.

Ahora vamos a crear una pequeña aplicación REST con Spring-Boot usando el driver JDBC de Yandex con Spring-JDBC. Creamos un proyecto Maven con el siguiente pom.xml:

En el directorio de resources creamos el fichero de configuración de Spring-Boot (application.yaml) bajo el directorio config:

Como podemos ver hemos configurado la conexión con ClickHouse que utilizará Spring-JDBC utilizando la librería de Hikari.

Ahora creamos la clase de arranque de Spring-Boot:

En el ejemplo vamos a crear un endpoint que nos retorne el número de vuelos de cada aerolínea filtrando por año. Para ello nos creamos el controlador que reciba la petición:

Ahora creamos el servicio:

Ahora el repositorio:

Y por último el modelo:

Ahora arrancamos la aplicación y con un client ejecutamos por ejemplo que nos retorne los vuelos por aerolínea realizados en 2016:

Como podéis ver los tiempos de respuesta de la petición están por debajo de 50 ms recorriendo los más de 17 millones de registros.

Se puede descargar el código completo desde:

4. Conclusión

Como habéis visto trabajar con ClickHouse para realizar analítica del dato es bastante sencillo ya que se trabajaría como cualquier otra base de datos. Lo realmente importante a la hora de trabajar con este tipo de base de datos es estructurar correctamente la información en base a las consultas que se vayan a realizar y elegir correctamente el tipo de tabla.

Lo único que hecho en falta es más documentación ya que la única documentación que existe es la documentación oficial. Aunque también hay que decir que es bastante buena y es suficiente para exprimir al máximo.

5. Referencias

Dejar respuesta

Please enter your comment!
Please enter your name here