La forma en que BigQuery almacena los datos es diferente a los modelos tradicionales de los sistemas relacionales. Este tipo de sistemas guardaban la información en tablas en las que cada fila era un registro diferente y cada columna una dimensión sobre ese registro, de ahí que a este sistema se le denomine almacenamiento orientado a registros o record-oriented storage en inglés.
Google Cloud usa un paradigma diferente basado en almacenar los datos en columnas en un sistema propietario al que ha llamado Capacitor. Cada columna de la tabla se almacena en un bloque de archivos independiente y todas las columnas se almacenan en un único archivo de capacitor, que se comprime y cifra en el disco. BigQuery utiliza patrones de acceso a consultas para determinar la cantidad óptima de fragmentos físicos necesario y cómo se codifican los datos para optimizar su posterior consulta y utilización.
En Capacitor los valores de cada campo, o columna, se almacenan de manera separada de forma que la carga de leer el fichero es proporcional al número de columnas que queremos recuperar. Esto no quiere decir necesariamente que cada columna tenga vida propia en su propio fichero, solo quiere decir que cada columna se almacena en un bloque en un fichero, que luego se comprime de manera independiente para optimizar la gestión de los datos lo máximo posible.
Lo más interesante de Capacitator es que en su modelo de optimización toma en consideración factores como el tipo de datos (p.e. es una larga cadena de de texto o un número entero) así como el uso que hacemos de los datos (algunas columnas se usan con más frecuencia que otras como filtros con la cláusula WHERE en SQL en las consultas) para volver a barajar las filas y codificar las columnas. Aunque todas las columnas están codificadas BigQuery elabora y usa estadísticas sobre los datos que se persisten y usan en la ejecución de las consultas.
La capa de persistencia de los datos, entendida como la capacidad de hacer que los datos estén siempre disponibles para su recuperación incluso en situaciones de fallos o caídas de los servidores, la proporciona el sistema de archivos distribuido de Google Colossus.
Colossus garantiza la durabilidad mediante algo llamado erasure encoding que fracciona los datos en fragmentos más pequeños denominados shards y guarda piezas redundantes (copias de la misma información) ubicadas en distintos discos e incluso en distintas zonas dentro de la misma región como se muestra en el gráfico. Todo esto se logra sin afectar la potencia de computación disponible para las consultas. Separar el almacenamiento de la computación permite escalar el almacenamiento al nivel de petabytes sin problemas y sin necesidad de añadir costosos recursos de procesamiento adicionales.
En BigQuery hay dos tipos de almacenamiento de datos, el activo y el de largo plazo o histórico. El almacenamiento activo recoge todos los datos que haya en tablas o particiones que se hayan modificado en los último 90 días. Esto tiene un impacto directo en los costes de almacenamiento ya que los datos históricos tienen una rebaja en costes de un 50%.
La Optimización del Almacenamiento
Hay dos herramientas que Google BigQuery pone a nuestra disposición para optimizar el rendimiento del almacenamiento de nuestros datos: el particionamiento de las tablas y la clusterización.
El Particionamiento
El particionamiento transforma una tabla para dividirla en diferentes segmentos en base a uno o más criterios. A cada segmento se le denomina una partición. Lo que nos permite el particionamiento es reducir el número de recursos que necesitamos para mover los datos en BigQuery. De esta forma BigQuery puede decidir cuál es el nivel de fragmentación óptimo de los datos (sharding) y la distribución de los mismos.
Este es un ejemplo de fragmentación partiendo de uno de los campos más habituales, la fecha en que se creo el registro. Podemos ver como se han creado varias segmentaciones o particiones en el lado derecho:
A la hora de realizar un filtro en una consulta a los datos en BigQuery sobre la columna particionada (fecha de creación) podemos reducir el número de datos que tiene que recorrer BigQuery para devolvernos el resultado de la consulta mejorando el tiempo de respuesta y reduciendo los costes de procesar los datos.
La clusterización
La clusterización es un método para organizar los datos en base al contenido desde una hasta cuatro columnas. Es una técnica que se suele usar con datos con una alta cardinalidad (la existencia de multitud de valores únicos en la columna) y para valores no temporales, es decir, que no cambien en el tiempo.
En este ejemplo tenemos la misma tabla particionada por fecha y luego clusterizada por las etiquetas (Tags). Al igual que la partición la clusterización nos ayuda a realizar de manera más eficiente los filtros de las columnas clusterizadas por un motivo muy parecido al que hemos visto en el particionamiento.
Otra ventaja de la clusterización esta en la realización de de cálculos sobre las columas clusterizadas al colocar contiguos los valores que comparten los mismos valores dentro de las columnas clusterizadas.
Qué proceso siguen los datos al llegar a BigQuery
- Codificar, comprimir y estadísticas tras analizar los tipos de datos los codifica, valora sus frecuencias y comprime los datos de la manera más óptima para la lectura de grandes cantidades de datos estructurados.
- Sharding es el proceso de partición de los datos para almacenarlos a continuación en dentro de una misma ubicación o incluso a través de varias ubicaciones como hemos visto. La gestión de la fragmentación de los datos es dinámica para ajustar los parámetros con el objetivo de optimizar las consultas.
- Encriptación BigQuery encripta los datos por defecto antes de escribir nada en el disco. Los datos se desencriptan automáticamente cuando un usuario autorizado trata de leerlos.
- Geo-replication En función de la región que hayamos definido en la configuración BigQuery replica de manera automática los datos a través de múltiples data centers en diferentes zonas dentro de la región.
¿Por qué hacer el sharding de los datos?
A medida que una aplicación crece, la cantidad de usuarios de la aplicación y la cantidad de datos que almacenamos aumentan con el tiempo. La base de datos se convierte en un cuello de botella si el volumen de datos se hace demasiado grande y demasiados usuarios intentan usar la aplicación para leer o guardar información de forma simultánea por lo que la aplicación se ralentiza y afecta a la experiencia del cliente. La partición de bases de datos es uno de los métodos para resolver este problema porque permite el procesamiento paralelo de conjuntos de datos más pequeños en todas las particiones.
Algunas formas de hacer llegar los datos a BigQuery
Hay varias formas en que podemos hacer que nuestros datos lleguen a BigQuery, los más habituales son los siguientes:
Ingesta de datos por lotes (Batch)
Es un proceso habitual cuando se trata de mover grandes volúmenes de datos cuando no necesitamos que los datos se procesen en tiempo real lo que nos permite programar el procesado de los datos cuando mejor nos convenga. Generalmente se trata de procesos en los que se realiza la tarea por lotes, a menudo de manera simultánea como en orden secuencial, un lote después de otro.
Ingestión de datos en tiempo real por streaming
Se diferencia con lo anterior en que el flujo no significa mover grandes cantidades de datos pero si que necesitamos que los datos se procesen en tiempo real o casi real. Estos datos deben procesarse de forma secuencial y gradual registro por registro o en ventanas de tiempo graduales. BigQuery nos ofrece soluciones via API para poder tener disponibles los datos a medida que sean ingestados.
Servicios de Transferencia de Datos
DTS (de sus siglas en inglés) se trata de una solución desarrollada por Google para la ingesta automática de datos desde alguna de las plataformas de datos del propio Google como Google Ads, YouTube o Campaign Manager. Esta misma solución se puede usar para la transferencia de datos desde Amazon S3 o Azure y desde soluciones de Data Warehouse como Teradata y Amazon Redshift.
Materialización de Consultas
La materialización de consultas SQL se refiere a los conjuntos de datos que se generan al ejecutar la consulta y almacenarla en la memoria física hasta que se completa la ejecución de la consulta. Estos datos materializados se tornan nulos y se libera la memoria para los siguientes procesos. Podemos verlo como una tabla temporal que se crea con los datos necesarios y que luego se descarta más adelante.