Optimiza el rendimiento de BigQuery DataFrames

BigQuery DataFrames te ayuda a analizar y transformar datos en BigQuery con una API compatible con Pandas. Para que el procesamiento de datos sea más rápido y rentable, puedes usar varias técnicas para mejorar el rendimiento.

En este documento, se describen las siguientes formas de optimizar el rendimiento:

Usa el modo de ordenamiento parcial

BigQuery DataFrames tiene una función de modo de ordenamiento, que aplica un orden de filas específico para operaciones como funciones de ventana y uniones. Puedes especificar el modo de ordenamiento configurando la propiedad ordering_mode en strict (conocido como modo de ordenamiento estricto, que es el predeterminado) o partial (conocido como modo de ordenamiento parcial). Usar el parámetro de configuración partial puede hacer que tus consultas sean más eficientes.

El modo de ordenamiento parcial es diferente del modo de ordenamiento estricto. El modo de ordenamiento estricto organiza todas las filas en un orden específico. Este ordenamiento total hace que los DataFrames de BigQuery funcionen mejor con Pandas, lo que te permite acceder a las filas por su orden con la propiedad DataFrame.iloc. Sin embargo, el orden total y su índice secuencial predeterminado impiden que los filtros en columnas o filas reduzcan la cantidad de datos analizados. Esta prevención se produce a menos que apliques esos filtros como parámetros a las funciones read_gbq y read_gbq_table. Para ordenar todas las filas del DataFrame, BigQuery DataFrames crea un hash de todas las filas. Esta operación puede provocar un análisis completo de los datos que ignore los filtros de filas y columnas.

El modo de ordenamiento parcial impide que BigQuery DataFrames cree un orden total para todas las filas y desactiva las funciones que necesitan un orden total, como la propiedad DataFrame.iloc. El modo de ordenamiento parcial también establece la clase DefaultIndexKind en un índice nulo, en lugar de un índice secuencial.

Cuando filtras un objeto DataFrame con el modo de ordenamiento parcial, BigQuery DataFrames no calcula qué filas faltan en el índice secuencial. El modo de ordenamiento parcial tampoco combina automáticamente los datos según el índice. Estos enfoques pueden aumentar la eficiencia de tus consultas. Sin embargo, ya sea que uses el modo de ordenamiento estricto predeterminado o el modo de ordenamiento parcial, la API de BigQuery DataFrames funciona como la API de Pandas que ya conoces.

Con los modos de ordenamiento parcial y estricto, pagas por los recursos de BigQuery que utilizas. Sin embargo, usar el modo de ordenamiento parcial puede reducir los costos cuando se trabaja con tablas grandes particionadas y agrupadas en clústeres. Esta reducción de costos se produce porque los filtros de filas en las columnas de clúster y partición reducen la cantidad de datos procesados.

Habilita el modo de pedido parcial

Para usar el ordenamiento parcial, establece la propiedad ordering_mode en partial antes de realizar cualquier otra operación con BigQuery DataFrames, como se muestra en el siguiente muestra de código:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

El modo de ordenamiento parcial evita las uniones implícitas de objetos BigQuery DataFrame no relacionados porque carece de un índice secuencial. En cambio, debes llamar de forma explícita al método DataFrame.merge para unir dos objetos de BigQuery DataFrames que se derivan de diferentes expresiones de tabla.

Las funciones Series.unique() y Series.drop_duplicates() no funcionan con el modo de ordenamiento parcial. En su lugar, usa el método groupby para encontrar valores únicos, como se muestra en el siguiente ejemplo:

# Avoid order dependency by using groupby instead of drop_duplicates.
unique_col = df.groupby(["column"], as_index=False).size().drop(columns="size")

Con el modo de ordenamiento parcial, es posible que el resultado de las funciones DataFrame.head(n) y Series.head(n) no sea el mismo cada vez que las ejecutes. Para descargar una muestra aleatoria pequeña de los datos, usa los métodos DataFrame.peek() o Series.peek().

Para obtener un instructivo detallado en el que uses la propiedad ordering_mode = "partial", consulta Cómo analizar las descargas de paquetes de PyPI con BigQuery DataFrames.

Soluciona problemas

Debido a que BigQuery DataFrames en modo de ordenamiento parcial a veces carece de un ordenamiento o un índice, es posible que encuentres los siguientes problemas cuando uses algunos métodos compatibles con pandas.

Error de pedido obligatorio

Algunas funciones, como DataFrame.head() y DataFrame.iloc, necesitan un orden. Para obtener una lista de las funciones que requieren ordenamiento, consulta la columna Requiere ordenamiento en APIs de Pandas compatibles.

Cuando un objeto no tiene orden, la operación falla con un mensaje OrderRequiredError como el siguiente: OrderRequiredError: Op iloc requires an ordering. Use .sort_values or .sort_index to provide an ordering.

Como indica el mensaje de error, puedes proporcionar un ordenamiento con el método DataFrame.sort_values() para ordenar por una o más columnas. Otros métodos, como DataFrame.groupby(), proporcionan implícitamente un orden total basado en las claves de agrupación.

Si el ordenamiento no es un orden total completamente estable para todas las filas, las operaciones posteriores podrían mostrar un mensaje de AmbiguousWindowWarning como el siguiente: AmbiguousWindowWarning: Window ordering may be ambiguous, this can cause unstable results.

Si tu trabajo puede manejar resultados que no siempre son los mismos, o si puedes verificar manualmente que tu ordenamiento es un ordenamiento total, puedes filtrar el mensaje AmbiguousWindowWarning de la siguiente manera:

import warnings

import bigframes.exceptions

warnings.simplefilter(
    "ignore", category=bigframes.exceptions.AmbiguousWindowWarning
)

Error de índice nulo

Algunas funciones, como las propiedades DataFrame.unstack() y Series.interpolate(), necesitan un índice. Para obtener una lista de las funciones que requieren un índice, consulta la columna Requiere índice en APIs de Pandas compatibles.

Cuando usas una operación que requiere un índice con modo de ordenamiento parcial, la operación genera un mensaje NullIndexError como el siguiente: NullIndexError: DataFrame cannot perform interpolate as it has no index. Set an index using set_index.

Como indica el mensaje de error, puedes proporcionar un índice con el método DataFrame.set_index() para ordenar por una o más columnas. Otros métodos, como DataFrame.groupby(), proporcionan de forma implícita un índice basado en las claves de agrupación, a menos que se establezca el parámetro as_index=False.

Almacena en caché los resultados después de operaciones costosas

BigQuery DataFrames almacena las operaciones de forma local y aplaza la ejecución de las consultas hasta que se cumplen ciertas condiciones. Esto puede hacer que las mismas operaciones se ejecuten varias veces en diferentes consultas.

Para evitar repetir operaciones costosas, guarda los resultados intermedios con el método cache(), como se muestra en el siguiente ejemplo:

# Assume you have 3 large dataframes "users", "group" and "transactions"

# Expensive join operations
final_df = users.join(groups).join(transactions)
final_df.cache()
# Subsequent derived results will reuse the cached join
print(final_df.peek())
print(len(final_df[final_df["completed"]]))
print(final_df.groupby("group_id")["amount"].mean().peek(30))

Este método crea una tabla temporal de BigQuery para almacenar tus resultados. Se te cobrará por el almacenamiento de esta tabla temporal en BigQuery.

Obtén una vista previa de tus datos con el método peek()

BigQuery DataFrames ofrece dos métodos de API para obtener una vista previa de los datos:

  • peek(n) devuelve n filas de datos, donde n es la cantidad de filas.
  • head(n) devuelve las primeras n filas de datos, según el contexto, donde n es la cantidad de filas.

Usa el método head() solo cuando el orden de los datos sea importante, por ejemplo, cuando quieras los cinco valores más grandes de una columna. En otros casos, usa el método peek() para recuperar datos de manera más eficiente, como se muestra en el siguiente muestra de código:

import bigframes.pandas as bpd

# Read the "Penguins" table into a dataframe
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")

# Preview 3 random rows
df.peek(3)

También puedes usar el método peek() para descargar una muestra aleatoria pequeña de datos mientras usas el modo de ordenamiento parcial.

Cómo aplazar la recuperación de datos de repr()

Puedes llamar al método repr() en BigQuery DataFrames con notebooks o el depurador de tu IDE. Esta llamada activa la llamada a head() que recupera los datos reales. Esta recuperación puede ralentizar el proceso iterativo de codificación y depuración, y también generar costos.

Para evitar que el método repr() recupere datos, establece el atributo repr_mode en "deferred", como se muestra en el siguiente ejemplo:

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

En el modo diferido, solo puedes obtener una vista previa de tus datos con llamadas explícitas de peek() y head().

¿Qué sigue?