Optimizar el rendimiento de BigQuery DataFrames

BigQuery DataFrames te ayuda a analizar y transformar datos en BigQuery mediante una API compatible con pandas. Para que el tratamiento 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:

Usar el modo de ordenación parcial

BigQuery DataFrames tiene una función de modo de ordenación que aplica un orden de filas específico a operaciones como las funciones de ventana y las combinaciones. Puede especificar el modo de ordenación definiendo la propiedad ordering_mode como strict (conocido como modo de ordenación estricto, que es el predeterminado) o partial (conocido como modo de ordenación parcial). Si usas el ajuste partial, tus consultas serán más eficientes.

El modo de ordenación parcial es diferente del modo de ordenación estricta. El modo de orden estricto ordena todas las filas de una forma específica. Este orden total hace que BigQuery DataFrames funcione mejor con pandas, lo que te permite acceder a las filas por su orden mediante la propiedad DataFrame.iloc. Sin embargo, el orden total y su índice secuencial predeterminado impiden que los filtros de columnas o filas reduzcan la cantidad de datos analizados. Esto solo ocurre si no aplicas 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 orden 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 orden parcial también asigna a la clase DefaultIndexKind un índice nulo en lugar de un índice secuencial.

Cuando filtras un objeto DataFrame con el modo de orden parcial, BigQuery DataFrames no calcula qué filas faltan en el índice secuencial. El modo de ordenación parcial tampoco combina automáticamente los datos en función del índice. Estas estrategias pueden aumentar la eficiencia de tus consultas. Sin embargo, tanto si usas el modo de orden estricto predeterminado como el modo de orden parcial, la API BigQuery DataFrames funciona como la API pandas.

En los modos de ordenación parcial y estricta, pagas por los recursos de BigQuery que utilices. Sin embargo, usar el modo de ordenación parcial puede reducir los costes al trabajar con tablas grandes agrupadas en clústeres y con particiones. Esta reducción de costes se produce porque los filtros de filas de las columnas de clúster y de partición reducen la cantidad de datos procesados.

Habilitar el modo de pedido parcial

Para usar el orden parcial, asigna el valor partial a la propiedad ordering_mode antes de realizar cualquier otra operación con los DataFrames de BigQuery, tal como se muestra en el siguiente ejemplo de código:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

El modo de orden parcial evita las uniones implícitas de objetos DataFrame de BigQuery no relacionados porque no tiene un índice secuencial. En su lugar, debes llamar explícitamente al método DataFrame.merge para combinar dos objetos DataFrame de BigQuery que procedan de expresiones de tabla diferentes.

Las funciones Series.unique() y Series.drop_duplicates() no funcionan con el modo de orden parcial. En su lugar, usa el método groupby para buscar 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")

En el modo de ordenación 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 ver un tutorial detallado en el que se usa la propiedad ordering_mode = "partial", consulta Analizar las descargas de paquetes de PyPI con BigQuery DataFrames.

Solución de problemas

Como BigQuery DataFrames en modo de ordenación parcial a veces no tiene un orden o un índice, es posible que te encuentres con los siguientes problemas al usar algunos métodos compatibles con pandas.

Error de pedido obligatorio

Algunas funciones, como DataFrame.head() y DataFrame.iloc, necesitan un orden. Para ver una lista de las funciones que requieren orden, consulte la columna Requires ordering (Requiere orden) en APIs de pandas admitidas.

Cuando un objeto no tiene ningún orden, la operación falla y se muestra 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 orden mediante el método DataFrame.sort_values() para ordenar por una o varias columnas. Otros métodos, como DataFrame.groupby(), proporcionan implícitamente un orden total basado en las claves de la agrupación.

Si el orden no es un orden total completamente estable para todas las filas, es posible que en operaciones posteriores se muestre un mensaje AmbiguousWindowWarning como el siguiente: AmbiguousWindowWarning: Window ordering may be ambiguous, this can cause unstable results.

Si tu trabajo puede gestionar resultados que no siempre sean los mismos o si puedes comprobar manualmente que tu orden es un orden total, puedes filtrar el mensaje AmbiguousWindowWarning de esta forma:

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 ver una lista de las funciones que requieren un índice, consulta la columna Requires index (Requiere índice) de APIs de pandas admitidas.

Cuando usas una operación que requiere un índice con el modo de orden 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 mediante el método DataFrame.set_index() para ordenar por una o varias columnas. Otros métodos, como DataFrame.groupby(), proporcionan implícitamente un índice basado en las claves de agrupación, a menos que se defina el parámetro as_index=False.

Almacenar 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 determinadas condiciones. Esto puede provocar 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 los resultados. Se te cobrará por el almacenamiento de esta tabla temporal en BigQuery.

Previsualizar los datos con el método peek()

BigQuery DataFrames ofrece dos métodos de API para previsualizar datos:

  • peek(n) devuelve n filas de datos, donde n es el número de filas.
  • head(n) devuelve las primeras n filas de datos, en función del contexto, donde n es el número de filas.

Utilice el método head() solo cuando el orden de los datos sea importante, por ejemplo, cuando quiera obtener los cinco valores más altos de una columna. En otros casos, usa el método peek() para obtener los datos de forma más eficiente, tal como se muestra en el siguiente ejemplo 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 pequeña muestra aleatoria de datos mientras usas el modo de ordenación parcial.

Aplazar la recuperación de datos de repr()

Puedes llamar al método repr() en BigQuery DataFrames con cuadernos o con el depurador de tu IDE. Esta llamada activa la llamada head(), que obtiene los datos reales. Esta recuperación puede ralentizar el proceso de depuración y programación iterativa, así como generar costes.

Para evitar que el método repr() recupere datos, asigna el valor "deferred" al atributo repr_mode, 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().

Siguientes pasos