top of page

BigQuery: ¿cuándo particionar tablas?

Foto del escritor: Daniela RBRDaniela RBR

Si trabajas con grandes volúmenes de datos en BigQuery, seguramente te habrás preguntado cómo optimizar tus consultas y gestionar los costos de forma más eficiente. Al investigar encontrarás que existen distintas configuraciones que se pueden aplicar a una tabla ,entre las cuales esta la posibilidad de particionarla, estrategia que figura como una de las más poderosas para lograrlo. Pero, ¿cuándo es realmente el momento adecuado para particionar una tabla? En esta nota exploraremos en profundidad los criterios y beneficios de la partición en BigQuery, analizaremos casos prácticos y desmitificaremos algunas ideas erróneas que rondan en torno a este tema.


¿Qué es una tabla particionada?

Supongamos que tenés una enorme colección de libros guardada en tu biblioteca, pero todos están mezclados, organizados únicamente según el orden en que los fuiste adquiriendo. En este caso, buscar un libro con alguna característica particular —por ejemplo, uno de ciencia ficción— se vuelve muy complicado, porque tendrías que revisar cada ejemplar para identificar aquellos que cumplen con ese criterio. Esto sería equivalente a tener una tabla plana en BigQuery y aplicar un filtro (WHERE).


Ahora, imaginá que decidís organizar tus libros en secciones o estantes siguiendo un criterio: uno para novelas de ciencia ficción, otro para thrillers, uno para biografías, y así sucesivamente. Cada sección representa una parte de tu colección, de modo que cada libro se clasifica en un solo grupo y, al unirlos, recuperás la colección completa. Este ejemplo equivale a tener una tabla particionada en BigQuery.


De la misma forma que, al buscar un libro de ciencia ficción, solo necesitás revisar la sección correspondiente, en una tabla particionada las consultas se realizan únicamente sobre el subconjunto relevante. Esto hace que la búsqueda sea mucho más rápida y eficiente, optimizando tanto el tiempo como el costo de procesamiento. Matemáticamente, este proceso se conoce como la partición de un conjunto: dividirlo en subconjuntos disjuntos —sin elementos en común— cuya unión constituye el conjunto original.


Tabla particionada: Una tabla particionada es una tabla en la que los datos se dividen en segmentos llamados particiones. Estos segmentos se crean en función de los valores de una columna de partición (por ejemplo, una columna de fecha o de rango numérico). [fuente documentación]


¿Qué ventajas en rendimiento y costo ofrece la partición?

Cuando realizás una consulta a una tabla particionada en BigQuery, el motor de consultas utiliza un proceso conocido como "partition pruning" o eliminación de particiones. Esto significa que, si tu consulta incluye un filtro sobre la columna que define la partición (por ejemplo, una fecha), BigQuery identifica y escanea únicamente aquellas particiones que contienen datos relevantes para el filtro.


Para que se pueda entender el impacto, hablemos de números concretos: supongamos que tenemos una tabla de 100 GB de datos. Si decidimos dejar la tabla plana, al hacer una consulta que filtre por un rango de fechas, BigQuery tendrá que escanear los 100 GB completos. Notarás que si tu consulta es:

SELECT *
FROM table_2024

tendrá el mismo coste que si es:

SELECT *
FROM table_2024
WHERE date >= "2024-12-01" and date <= "2024-12-31"

a pesar de que el output nos dará menos filas al realizar esta segunda consulta.


En cambio, si tomamos dicha tabla y la particionamos por la columna de fecha, esto implicaría que en promedio cada día representaría una partición de 273 MB.

Tamaño de cada partición 100 GB / 366 días ≈ 0.273 GB ≈ 273 MB

Entonces la consulta en lugar de escanear 100 GB, a escanear 8.46 GB aprox.

31 × 273 MB ≈ 8.463 GB

Hay que tener en cuenta que en BigQuery el costo de una consulta se basa en la cantidad de datos que se escanean. Según la documentación [link], en este momento, la tarifa para consultas on-demand es de $6.25 USD por TiB escaneado. Es importante notar que el término "TiB" (tebibyte) se refiere a 2^40 bytes, lo cual es ligeramente diferente a un terabyte decimal (1 TB = 10^12 bytes).

Entonces, volviendo a nuestro ejemplo, de la tabla de 100 GB consultada para el mes de diciembr, los cálculos serían los siguientes:

  • 1 TiB ≈ 1.1 TB.

  • 100 GB = 0.1 TB

    ⇒ 1 TiB = 1024 GB

    ⇒ 100 GB ≈ 0.09766 TiB.

  • ∴ El costo aproximado para 100 GB sería 0.09766 × $6.25 ≈ $0.61 USD.

  • ∴ El costo aproximado para 8.463 GB sería 0.00826 × $6.25 ≈ $0.05 USD.


Por lo tanto, estamos hablando de e costo de la consulta se redujo aproximadamente en un 91.8% al particionar la tabla, ¡una locura!


En resumen, los beneficios se ven en:

  • Eficiencia: Al aplicar un filtro sobre la columna de partición, se "poda" la tabla, escaneando solo el subconjunto necesario.

  • Costo: Menos datos escaneados implican un menor costo de procesamiento en BigQuery.

  • Rendimiento: Al reducir la cantidad de datos a procesar, las consultas se ejecutan más rápido.


Entonces, no solo mejora la eficiencia en la consulta, sino que también optimiza el uso de recursos y reduce los costos, lo cual es especialmente importante cuando se manejan grandes volúmenes de datos.


También es importante tener en cuenta que, en BigQuery, el costo de almacenamiento se basa en la cantidad de datos que almacenás y no varía significativamente si la tabla está particionada o es plana. Es decir, el precio por GB almacenado es el mismo para ambas estructuras.


¿Siempre es una buena idea particionar?

Y aquí está el kit de la cuestión: porque, si bien parece ideal, no siempre tiene sentido hacerlo. Volvamos al ejemplo de la biblioteca: organizar un género por estante suena increíble, ya que si me dan ganas de leer una novela negra, podría encontrar mis opciones sin mucho esfuerzo. Ahora supongamos que tengo 15 novelas y cada una es de un género distinto; en ese caso, no tendría mucho sentido ordenar 15 libros en 15 estanterías distintas, ¿no? Esto en BigQuery es lo que se conoce como "overhead".


Overhead: En el contexto de sistemas informáticos, se refiere al coste adicional en recursos (como tiempo de procesamiento, memoria y espacio de almacenamiento) que se requiere para gestionar, coordinar o soportar una operación principal. Es decir, es el “gasto extra” necesario para que el sistema realice tareas de administración o control, sin aportar directamente al resultado final de la operación.

Entonces, el "overhead" de una tabla particionada se refiere al pequeño costo extra que supone organizar y gestionar la tabla en particiones en lugar de tenerla toda junta. En BigQuery, ese overhead es principalmente el costo de gestionar la información extra (la "metadata") de cada partición.


Es importante resaltar que si bien este costo adicional no se refleja como un cargo extra en dinero, ya que está incluido en el sistema y no genera un cargo separado en tu factura, sí tiene implicaciones en el rendimiento y en la eficiencia de la gestión de los datos, motivo por el cuál debemos preguntarnos si tiene sentido o no hacerlo.


Si buscas en la documentación oficial de BigQuery no se utiliza siempre el término "overhead" de manera explícita, pero sí se hace referencia al impacto que puede tener tener particiones demasiado pequeñas. Al ver la sección de Mejores Prácticas para tablas particionadas  [link documentación] se recomienda que cada partición contenga al menos 1 GB de datos. Esta recomendación, evidentemente no es para ahorrar plata, sino para evitar que se generen demasiadas particiones muy pequeñas, lo cual puede impactar en el rendimiento del sistema de las siguientes maneras:

  • Manejo de metadatos: Cada partición genera información adicional (metadatos) que BigQuery tiene que gestionar. Si tenés muchas particiones con solo una fila cada una, ese overhead en metadatos puede hacer que las operaciones internas sean menos eficientes.

  • Optimización de consultas: El objetivo de particionar es que, al filtrar, BigQuery tenga que escanear solo la parte relevante de la tabla. Si las particiones son muy pequeñas, la ventaja de saltarse grandes volúmenes de datos se diluye, y puede complicarse la optimización de las consultas.

  • Límites internos: BigQuery tiene ciertos límites en cuanto a la cantidad de particiones que se pueden tener en una tabla (tope de 10k particiones). Tener demasiadas particiones pequeñas podría acercarte a esos límites y generar problemas de administración [link documentación]


En resumen, no se trata de "particionar todo y listo", ya que particionar sin criterio sería equivalente a que pedís una bebida fría en un bar y, al recibirla, te la entregan con un sleeve de cartón (esa manga térmica que se usa para bebidas calientes). La estrategia de particionar debe alinearse con el volumen de datos y el patrón de consultas que vas a realizar. De esa forma, asegurás que la organización de los datos realmente aporte mejoras en las consultas sin sobrecargar el sistema con un exceso de particiones.


¿Cómo anticiparnos para decidir si hay que particionar o no?

Tal como mencioné, la recomendación es que cada partición tenga, al menos, 1 GB. Entonces, para poder anticiparnos a si una tabla la debemos particionar o no, debemos estimar el peso total de la tabla, o que podrá alcanzar la tabla, y calcular cuántas particiones se generarían. Con esta información, podremos decidir si realmente conviene o no particionarla.


Para calcular el costo total de almacenamiento de una tabla tenemos que:

  1. Calcular el número de filas que tendrá.

  2. Calcular el costo de almacenamiento según la documentación.


Para que sea más simple de entender, voy a dar un ejemplo con el que trabajé esta semana que fue el que me llevó a toda esta investigación.

  • Información de la tabla: Cantidad de seguidores por día, por red social, por unidad de negocio de la empresa.


Entonces, para poder predecir el tamaño aproximado de la tabla vamos a hacer un cálculo de permutaciones, para ello vamos a indicar el número de posibilidades en cada columna dimensional.

Columna

Tipo de dato

Detalle

Posibilidades

Fecha

Date

Histórico de 1 año y 4 meses

468

Unidad de negocio

String

Se trabaja con 5 unidades de negocio

5

Red social

String

Se trabajan con 7 redes sociales,

7

Entonces, el número máximo de permutaciones que se pueden dar es 16 380, siendo este el número aproximado de filas que se pueden conseguir,

468 x 5 x 7 = 16 380


BigQuery utiliza un almacenamiento columnar y tiene tamaños estimados por tipo de dato [link documentación]:

Tipo de Dato

Tamaño Aproximado

INT64

8 bytes

FLOAT64

8 bytes

STRING

Longitud * 2 bytes

BOOLEAN

1 byte

DATE

4 bytes

TIMESTAMP

8 bytes

Para calcular el almacenamiento de la tabla, debemos sacar el precio promedio por fila y luego multiplicarlo por el número de filas obtenido.

Peso promedio por fila ≈ ∑(Peso de cada columna)

Tamaño Total ≈ Peso promedio por fila × Número de filas


Entonces, volviendo al ejemplo del que partimos, para calcular el costo de una fila debemos ver cuanto cuesta cada columna.

Columna

Tipo de Dato

Tamaño (bytes)

Fecha

DATE

4

Unidad de negocio

STRING (10)

20

Red social

STRING (15)

30

Seguidores

INT64

8

  • 1 fila tiene un dato en fecha, uno string 10, uno string 15 y un entero.

    ⇒ 4+20+30+8 = 62 bytes por fila

    ⇒ 62 bytes x  16 380 = 1,015,560 bytes

    ⇒ ≈ 992 KB

    ⇒ ≈ 0.97 MB

    ≈ 0.00095 GB ⟺ aprox. a la milésima parte de 1 GB


Sobre estos cálculos hay que tener en cuenta:

  1. Se esta calculando el número de permutaciones máximas, es decir que si no todas las unidades de negocio tienen todas las redes sociales se reduciría el número de filas.

  2. Al decidir el peso de las columnas "STRING", se debe seleccionar el caso que mayor longitud tenga. Por ejemplo "X" tendrá un peso de 2 bytes, mientras que "instagram" tendra un peso de 18 bytes. De esta manera sabremos que estamos obteniendo el tope máximo.


Y la conclusión indiscutida es: este tamaño es pequeño y claramente no justifica la necesidad de particionar, ya que BigQuery optimiza mejor tablas planas para este volumen de datos.


Lo último que quedará es pensar en que si bien esta extracción es estática, la tabla no lo es, dado que se seguirán agregando filas con datos. Entonces, ¿puede que ahora no tenga sentido particionar pero más adelante si? Esta es una pregunta importante, porque tenemos que pensar en que la idea es no modificar la tabla a futuro. y para ello vamos a hacer un cálculo paredido pero estimando cambios


Columna

Tipo de dato

Detalle

Posibilidades

Fecha

Date

Estimamos un histórico de 5 años

1825

Unidad de negocio

String

Se trabaja con 10 unidades de negocio

10

Red social

String

Se trabajan con 60 redes sociales,

60

  • Nuevo número de filas: 1825 x 10 x 60 = 1 095 000

    Si una fila son 62 bytes 

    ⇒ 62 bytes x  1 095 000 = 67 890 00 bytes

    ⇒ ≈ 992 KB

    ⇒ ≈ 6.47 MB

    ≈ 0.00632 GB ⟺ aprox. a la 157ª parte de 1 GB


Incluso con estas proyecciones, la tabla sigue siendo pequeña en comparación con el umbral de 1 GB por partición, lo que indica que no justifica la necesidad de particionar.


En conclusión, esta tabla, en ambos escenarios —actual y futuro— resulta demasiado pequeña para aprovechar los beneficios de la partición en BigQuery. Particionar implicaría un overhead en la gestión de metadatos sin ofrecer ventajas significativas en el rendimiento de las consultas.



Te paso la idea en limpio y resumida

Si bien particionar una tabla en BigQuery puede mejorar el rendimiento y reducir costos, es importante hacerlo con criterio. Como regla general, una tabla debería tener más de 10 GB de datos para justificar la partición, y cada partición debería acercarse al umbral de 1 GB. Esto significa que, por ejemplo, particionar por día no es siempre la mejor opción si los datos diarios no alcanzan ese tamaño.


La clave está en evaluar el volumen y el crecimiento de tus datos para elegir una estrategia que aporte beneficios reales sin generar overhead innecesario. Con esta mentalidad, optimizar tus consultas y gestionar tus recursos se vuelve una decisión informada y efectiva.



¡Gracias por leer!

y no te olvides que le podés dar "me gusta" a esta nota sin haberte logueado.





14 visualizaciones0 comentarios

Comments


bottom of page