BD como servicio para millones de registros a bajo costo usando BigQuery y Cloud Functions de Google

Nicolas Riesco
GDG Cloud Santiago
Published in
3 min readAug 5, 2020
Photo by Jan Antonin Kolar on Unsplash

Administrar bases de datos es complejo y ocupar una BD como servicio puede ser muy caro para millones de registros. Con GPC se puede lograr a un bajo costo (incluso $0) y con un servicio de alta calidad.

El costo final dependerá obviamente de los datos a cargar, de la cantidad de consultas al mes y las optimizaciones a BigQuery que se hagan.

Pero, ¿Qué se necesita para lograr esto? Aparte de conocimientos mínimos de bases de datos relacionales y tener todo configurado en tu cuenta de GCD se requiere:

  1. Tener alguna forma de procesar los datos de entrada y dejarlos en un formato (por ejemplo JSON)
  2. Subir esos datos
  3. Cargar los datos en BigQuery
  4. Consultar los datos con una API

Punto 1

Se puede ocupar un programa en nodejs que lea los datos de entrada, en este caso un CSV con “anchos fijos”.

A considerar:

  1. Como los datos de entrada y salida son enormes es muy fácil tener problemas de memoria y capacidades (largo de string por ejemplo) por lo que es recomendable, y generalmente necesario, trabajar con buffers/streams.
  2. Read streams: https://nodejs.org/en/knowledge/advanced/streams/how-to-use-fs-create-read-stream/
  3. Write streams: https://nodejs.org/en/knowledge/advanced/streams/how-to-use-fs-create-write-stream/

Punto 2

Subir un archivo de varios Gigabytes puede ser complejo. Pero existe una herramienta que hace esto más fácil, gsutil.

A considerar:

  1. Al copiar un archivo grande se recomienda ocupar “parallel composite uploads”
  2. Existe un bug asociado al versión de python por lo que puede ser necesario que tengas que recurrir a algunos trucos como `export CLOUDSDK_PYTHON=/usr/bin/python2.7` más información acá: https://github.com/GoogleCloudPlatform/gsutil/issues/961#issuecomment-663565856
  3. El comando a ocupar es: `gsutil -o GSUtil:parallel_composite_upload_threshold=100M cp archivoASubir.json gs://$BUCKET_NAME`

Punto 3

En BigQuery se pueden importar datos desde tu bucket y si están en el formato correcto determina los tipos de datos. Esto funciona para algunos casos pero es preferible definir una suerte de índice para que las consultas sean más eficientes. BigQuery es muy rápido así que probablemente la eficiencia sea más por el lado del costo de la consulta que por la velocidad.

Si quieres crear una tabla con un key numérico este es un ejemplo:

CREATE TABLE
`foo.var.mi_tabla`
PARTITION BY
RANGE_BUCKET(miKeyNumerico, GENERATE_ARRAY(1, 100000000, 10000))
AS SELECT
1 AS miKeyNumerico,
1 AS atributoNumerico1,
"" AS miString1,
"" AS miString2

Luego puedes volver a “crear” la tabla mi_tabla y al final en las opciones avanzadas eliges que sobre-escriba todo o bien le agregue información a la tabla existente.

Más detalles acá:

Punto 4

Puedes partir de este código y adaptarlo a tu función: https://github.com/googleapis/nodejs-bigquery/blob/master/samples/query.js

Recuerda agregar las dependencias en package.json como este ejemplo de lo contrario no te funcionará:

{
"name": "sample-http",
"version": "0.0.1",
"dependencies": {
"@google-cloud/bigquery": "^5.1.0"
}
}

Finalmente tendrás una API de este estilo:

https://us-central1-foo-var.cloudfunctions.net/my-function?myKeyValue=111111111

--

--