Optimización de costes en BigQuery: ¿cómo reducir tu factura de forma significativa? 

BigQuery es una de las soluciones de almacenamiento en la nube más usadas en el mundo (fuente). Aunque las ofertas de Amazon y Microsoft sean más populares a nivel global, la realidad es diferente en algunos sectores como el nuestro porque existen conectores nativos con BigQuery (Google Search Console & Google Analytics 4) que nos incitan a usar su producto en lugar de la competencia. 

Cuando usamos el servicio por primera vez, siempre tenemos la misma duda: ¿cuánto me va a costar? En este artículo, os voy a explicar cómo lo podéis estimar y qué buenas prácticas tenéis que aplicar para evitar sorpresas y mantener a raya tus costes en BigQuery.

¿Cómo funciona el modelo de facturación de BigQuery? 

BigQuery tiene una página detallando sus precios pero puede agobiar bastante al principio. A modo de resumen, que sepáis que se os va a cobrar por dos cosas: 

  • Almacenamiento. Contad con un promedio de 30€ / TB / mes, teniendo en cuenta que tenéis que gestionar un proyecto bastante grande para generar esta cantidad de datos. 
  • Consulta. 6.25€ / TB. Es decir que si hacéis un select * sobre una tabla que incluye 1TB de datos, BigQuery os cobrará 6.25€. 

El gran problema es que si bien podemos estimar fácilmente la cantidad de datos que un proyecto puede llegar a generar, las consultas dependen del uso que se darán de estos datos. 

  • ¿Vamos a realizar muchas consultas? 
  • ¿Muchas personas van a abrir los informes conectados a nuestras bases de datos? 

Sin embargo, suele ser un falso problema porque si aplicáis buenas prácticas de optimización de costes que voy a explicar en este artículo, no váis a tener problemas hasta para proyectos grandes. 

Definir un presupuesto en BigQuery 

Aunque apliquemos optimizaciones, siempre es mejor tener un sistema de alertas por cualquier cosa. Podemos crear un presupuesto desde el menú de GCP. Primero, tenemos que acceder a la sección de facturación … 

… y definir un presupuesto. 

Cuidado: un presupuesto no es un límite: GCP nos seguirá cobrando si nos pasamos, pero por lo menos recibiremos un aviso y podremos ver qué está pasando. 

Consultar costes de BigQuery

Si por lo que sea necesitáis consultar los costes detallados de BigQuery, tenéis suerte. Se generan, de forma automática, tablas con todo el detalle. Asumiendo que tengamos nuestros datos en la UE, podríamos ejecutar la siguiente consulta …

SELECT
*
FROM `region-eu`.INFORMATION_SCHEMA.JOBS

… para obtener todo el detalle de las consultas y los costes asociados. 

Hay muchos campos, pero vamos a ver que únicamente algunos suelen ser interesantes.

  1. project_id: el ID del proyecto en GCP 
  2. user_email: el e-mail del usuario vinculado con la consulta. Si tenéis exportación de GSC o GA4 activadas, podéis llegar a ver valores como search-console-data-export@system.gserviceaccount.com
  3. statement_type: el tipo de consulta (SELECT, CREATE o DELETE)
  4. total_bytes_billed: la cantidad de datos que se nos ha cobrado. Puede ser diferente de total_bytes_processed.

Si queremos saber cuál es coste total por usuario, podemos ejecutar la siguiente consulta

SELECT
project_id,
user_email,
SUM(total_bytes_billed/1024/1024/1024) as gb_billed
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
group by project_id, user_email
order by gb_billed desc

En este caso, el usuario vinculado a la exportación de los datos de BigQuery me ha generado un coste de casi 11 GB, es decir de 0,068€. 

Para las consultas que ejecutamos con Looker Studio, las podemos aislar con el siguiente SQL. Cabe destacar que todos los costes se asignan al e-mail que es propietario de los datos del Looker Studio (es decir la persona que ha configurado el conector). 

WITH raw_data AS (
SELECT
DISTINCT
project_id,
user_email,
total_bytes_billed/1024/1024/1024 as gb_billed,
value as requestor
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
left join unnest(labels) l
where key = "requestor"
)

select
distinct
project_id,
user_email,
requestor,
SUM(gb_billed) as gb_billed
from raw_data
group by project_id, user_email, requestor
order by gb_billed desc

Buenas prácticas para optimizar los costes 

Cómo váis a ver, optimizar costes es bastante sencillo. Existen métodos más avanzados que no voy a detallar porque no van a ser útiles para la mayoría. Sin embargo, que sepáis que estas técnicas me han permitido bajar la factura promedia de un proyecto de 80% de un día para otro. 

Crear particiones en mis tablas

Algunas tablas pueden llegar a ser muy grandes.

Sin embargo, estas tablas se suelen consultar parcialmente, en base a un campo específico. En marketing digital, casi siempre tenemos una fecha. Dado que cuando hacemos una consulta, BigQuery nos cobra por los datos procesados, esto crea un nivel de ineficiencia muy grande: si necesitamos los datos de 3 días para una tabla de 10 años, vamos a pagar mucho más de lo que realmente necesitamos.

Particionar nos permite dividir nuestra tablas en base a los valores de una columna (en general fechas) para limitar los costes. Cuando aplicamos un filtro sobre esta columna, BigQuery consultará únicamente las sub-tablas que corresponden a los valores de nuestra partición 

(fuente)

Ejemplo con nuestra tabla de 2TB:

Esta consulta costaría más de 13€ en una tabla sin particionar, pero aquí cuesta únicamente 0,018€. ¡Ni tan mal! 

Definir el vencimiento de las particiones en BigQuery 

PROBLEMA: pago por el almacenamiento de datos que ya no voy a usar nunca 

Aunque el almacenamiento sea barato, tampoco tiene sentido acumular datos que no vamos a usar nunca. Por ejemplo, ¿creéis que váis a consultar el tráfico de vuestro proyecto para el año 2015? 

En una tabla particionada, podemos definir el vencimiento. Por ejemplo, si queremos que los datos que tienen más de 10 años de antigüedad se eliminen automáticamente, podemos ejecutar el siguiente código: 

ALTER TABLE mydataset.mytable
  SET OPTIONS (
    -- Sets partition expiration to 10 years
    partition_expiration_days = 3650);

Más información aquí

Aplicar cluster en mis tablas en BigQuery 

El clustering es bastante similar al concepto de particiones. Además de crear sub-tablas sobre una columna, podemos crear otras sub-tablas en base al valor de otras columnas.

Si regresamos a nuestro ejemplo de antes y queremos los datos de un país y un día únicamente

Impresionante, ¿no? Nuestra consulta ha pasado de 

  • 13€ (tabla sin particionar) 
  • 0,018€ (tabla particionada) 
  • 0,003€ (tabla particionada y con clustering sobre el campo market

Si abusamos del clustering, es probable que BigQuery sea menos eficiente, entonces mi consejo es

  1. Usar columnas que usamos bastante en los filtros: en mi caso, market
  2. Usar columnas que contienen muchos valores únicos
  3. Máximo 4 columnas para clusterizar

Optimizar el contenido de vuestras tablas 

Ahora, todos estos consejos son maravillosos pero ya os digo que si no aplicáis este último, no os servirán (casi de nada). El error que muchos cometen es usar los datos brutos para sus informes. Vamos a usar un caso hipotético y bastante exagerado para que entendáis el problema. Imaginemos que tenemos una tabla de 1.8 TB con los siguientes campos: 

  1. date: fecha – 100 valores posibles 
  2. market: dominio del proyecto – 10 valores posibles 
  3. device: dispositivo usado por el usuario – 4 valores posibles 
  4. country: país en el cuál se encuentra el usuario – 150 valores posibles 
  5. sessions: número de sesiones 

En base a lo que acabamos de indicar, tendremos un total de 600.000 filas en nuestra tabla, es decir 3MB por fila aproximadamente. Como os decía, este ejemplo está exagerado porque es imposible que una fila pese tanto en BigQuery. 

Si usamos esta base de datos para construir un Looker Studio dónde usamos todos los campos excepto el country, estamos creando un nivel de ineficiencia muy grande. En efecto y por mucho que usemos particiones y clustering, estamos multiplicando los costes por 150 porque hay una dimensión, country, que tiene 150 valores únicos, que realmente no necesitamos. 

Una consulta que debería costar 0.1€ realmente costará 15€. 

Por lo tanto, tenéis que: 

  • Implementar un flujo de datos para crear una nueva tabla sin la columna country. Se puede lograr fácilmente con DBT o Dataform. El código sería muy similar al código indicado abajo. 
SELECT
date,
market,
device,
SUM(sessions) as sessions
FROM mytable
GROUP BY all 

Esta tabla nueva os va a incrementar vuestros costes de almacenamiento, pero seguirá siendo mucho más eficiente porque se van a incrementar <1% cuando los costes de consulta van a disminuir >99%. 

  • Cambiad la fuente de vuestro Looker para que use la nueva tabla, que incluye únicamente los datos que necesitáis 

¿Realmente es tan sencillo? 

En la gran mayoría de los casos, aplicar lo que os he comentado en este artículo es suficiente para mantener los costes bajo control. De hecho, en muchos proyectos ni vais a llegar a pagar 1€. 

BigQuery no es caro, pero puede llegar a serlo si se usa de forma ineficiente. 

Antoine Eripret
Antoine Eripret

SEO desde 2016, trabajo en la intersección entre SEO, ingeniería de datos y automatización. Me gusta sobre todo Airflow, SQL (BigQuery), DBT/Dataform y Python.

Deja un comentario