← Todos los artículos

LIMIT 10 no la abarata: BigQuery factura los bytes que lee, no las filas que devuelve

Un SELECT * con LIMIT 10 devuelve diez filas y puede facturar la tabla entera. Cómo guarda y lee BigQuery los datos, y cómo hacer que cada consulta lea menos.

Paso 1 de 6 Un SELECT * con LIMIT 10 sobre una tabla de 2 TiB. La consola devuelve 10 filas.
  1. Un SELECT * con LIMIT 10 sobre una tabla de 2 TiB. La consola devuelve 10 filas.
  2. Pero BigQuery guarda los datos por columnas y lee de arriba abajo cada columna que seleccionas: las seis.
  3. Bajo demanda se factura por bytes leídos, a 6,25 $ por TiB. Las 10 filas no cuentan: 12,50 $ cada vez.
  4. La causa: LIMIT solo recorta el resultado. En una tabla sin clustering, los bytes leídos son los mismos.
  5. La solución: pedir solo tres columnas y filtrar siete días de la partición. La lectura baja a 6 GiB.
  6. Compruébalo antes de ejecutar: el editor muestra cuántos bytes procesará la consulta.

Abres el export de GA4 o una tabla de ventas en BigQuery, escribes SELECT * FROM shop.events LIMIT 10 para ver qué hay dentro y recibes diez filas en un par de segundos. Parece una consulta minúscula. En la factura no lo es: en el modelo bajo demanda, BigQuery cobra por los bytes que lee, y diez filas de resultado pueden suponer leer de arriba abajo todas las columnas de la tabla.

Cómo es una consulta “pequeña” que sale cara

La consulta devuelve diez filas, pero la pestaña Información del trabajo (Job information) dice otra cosa:

  • Bytes procesados y Bytes facturados muestran el tamaño de las columnas seleccionadas, no el del resultado. En una tabla de 2 TiB con SELECT *, 2 TiB.
  • El editor ya lo avisaba antes de ejecutar: Esta consulta procesará 2 TiB. Añadir LIMIT 10 no cambia esa cifra.
  • A final de mes, la línea de BigQuery en la factura crece con consultas que “solo miraban unas filas”, a menudo informes programados o dashboards que lanzan lo mismo cada hora.

Por qué BigQuery lee la tabla entera

La factura es consecuencia de cómo está construido BigQuery.

  • El almacenamiento es columnar. BigQuery no guarda las filas una detrás de otra. Cada columna se guarda por separado, comprimida, en un formato llamado Capacitor. Una consulta solo lee las columnas que nombra, y las lee enteras: SELECT * las nombra todas.
  • Almacenamiento y cómputo están separados. Las tablas viven en Colossus, el sistema de archivos distribuido de Google. Cuando pulsas Ejecutar, los slots (las unidades virtuales de cómputo de BigQuery) leen los datos en paralelo por la red de Google.
  • Tu SQL se convierte en un plan por etapas. Cada slot lee y filtra su trozo, un shuffle reagrupa los resultados parciales y una etapa final los une en una sola respuesta. Se ve en la pestaña Gráfico de ejecución (Execution graph). LIMIT se aplica al final, sobre el resultado: para entonces las columnas ya se han leído.
  • El precio bajo demanda cuenta bytes leídos. 6,25 $ por TiB a precio de lista (algunas regiones varían), con el primer TiB de cada mes gratis. Son bytes lógicos: el tamaño de cada valor según su tipo de dato, no el tamaño comprimido en disco. Las filas devueltas no influyen en el precio.

La guía de costes de Google lo dice sin rodeos: en una tabla sin clustering, aplicar LIMIT no reduce los bytes leídos. En una tabla con clustering sí puede, porque BigQuery puede dejar de leer bloques antes. Los resultados en caché son gratis, y con el precio por capacidad (ediciones de BigQuery) pagas horas de slot en lugar de bytes, así que la misma consulta cuesta distinto.

Cómo ver lo que lee de verdad una consulta

  1. Antes de ejecutar, mira la estimación en la esquina superior derecha del editor: Esta consulta procesará X. Quita el LIMIT y no cambia; quita columnas y sí.
  2. Después de ejecutar, abre Información del trabajo y compara Bytes procesados con Bytes facturados (la facturación redondea al MB, con un mínimo de 10 MB por tabla referenciada y por consulta).
  3. Para encontrar las consultas que más cuestan, consulta total_bytes_billed en INFORMATION_SCHEMA.JOBS de tu proyecto o región, ordenado de mayor a menor. Las consultas programadas y los dashboards repiten su coste en cada ejecución.

Cómo hacer que cada consulta lea menos

  • Nombra solo las columnas que necesitas. SELECT event_date, event_name, revenue lee tres columnas en lugar de todas. Si solo quieres ver qué contiene una tabla, usa la pestaña Vista previa de la tabla, que no factura bytes.
  • Filtra por la partición. En una tabla particionada por fecha, un filtro con valores fijos sobre la columna de partición (WHERE event_date BETWEEN '2026-10-22' AND '2026-10-28') solo lee esas particiones. Puedes hacer ese filtro obligatorio con la opción require_partition_filter. El export de GA4 no está particionado sino dividido en una tabla por día: ahí lo equivalente es filtrar _TABLE_SUFFIX, que es el siguiente artículo de esta serie.
  • Aplica clustering a las tablas grandes sobre las columnas por las que más filtras (por ejemplo event_name), para que BigQuery pueda saltarse los bloques que no coinciden.
  • Mira la estimación antes de pulsar Ejecutar. En las consultas que se lanzan solas, usa un dry run y define Máximo de bytes facturados: si una consulta fuese a leer más, falla sin facturar.

Documentación de Google Cloud: precios de BigQuery, estimar y controlar costes, plan y cronología de la consulta y BigQuery under the hood (en inglés).

Cómo comprobar que la consulta lee menos

  • La estimación del editor baja al quitar columnas y añadir el filtro de partición: en el ejemplo, de 2 TiB a 6 GiB.
  • Los Bytes facturados de Información del trabajo coinciden con la estimación una vez ejecutada.
  • En INFORMATION_SCHEMA.JOBS, el total_bytes_billed de las consultas programadas y dashboards que has cambiado baja desde la siguiente ejecución.

El tamaño de la tabla, las cifras de bytes y el coste por ejecución del ejemplo son ilustrativos.