Optimiza el rendimiento de BigQuery DataFrames

Puedes optimizar tus flujos de trabajo de BigQuery DataFrames para analizar y transformar datos con una API compatible con pandas y, al mismo tiempo, mantener bajos los tiempos de ejecución y los costos. Aplicar técnicas de optimización específicas, como el modo de ordenamiento parcial y el almacenamiento en caché de resultados, te permite procesar datos con mayor rapidez y rentabilidad.

Usa el modo de ordenamiento parcial

BigQuery DataFrames tiene una función de modo de orden, que aplica un orden de filas específico para operaciones como funciones analíticas y uniones. Puedes especificar el modo de ordenamiento configurando la propiedad ordering_mode como strict (conocido como modo de ordenamiento estricto, que es el valor 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 orden estricto organiza todas las filas en un orden específico. Este orden total hace que BigQuery DataFrames funcione 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 de datos completo 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 orden parcial, BigQuery DataFrames no calcula qué filas faltan en el índice secuencial. El modo de orden parcial tampoco combina datos de forma automática según el índice. Estos enfoques pueden aumentar la eficiencia de tus consultas. Sin embargo, ya sea que uses el modo de orden estricto predeterminado o el modo de orden parcial, la API de BigQuery DataFrames funciona como la API de Pandas conocida.

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

Habilita el modo de ordenamiento parcial

Para usar el orden parcial, establece la propiedad ordering_mode en partial antes de realizar cualquier otra operación con BigQuery DataFrames, como se muestra en la 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 de BigQuery DataFrames no relacionados, ya que carece de un índice secuencial. En su lugar, debes llamar de forma explícita al método DataFrame.merge para unir dos objetos de BigQuery DataFrames que deriven de diferentes expresiones de tabla.

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 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 pequeña y aleatoria 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 Analiza las descargas de paquetes de PyPI con BigQuery DataFrames.

Soluciona problemas

Debido a que BigQuery DataFrames en el modo de ordenamiento parcial a veces carece de un orden o í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 orden, consulta la columna Requiere orden 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 se indica en el mensaje de error, puedes proporcionar un orden con el método DataFrame.sort_values() para ordenar por una o más columnas. Otros métodos, como DataFrame.groupby(), proporcionan de forma implícita un orden total basado en las claves de agrupación.

A diferencia de pandas, si estás en el modo de ordenamiento parcial, ejecutar el mismo código puede producir resultados diferentes cada vez que lo ejecutes. Para garantizar resultados coherentes, usa un orden total estable para todas las filas.

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 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 se indica en 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 cumplan ciertas condiciones. Esto puede hacer que se ejecuten las mismas operaciones 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 cobra 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, en el que n es la cantidad de filas.

Usa el método head() solo cuando el orden de los datos sea importante, por ejemplo, cuando quieras obtener los cinco valores más grandes de una columna. En otros casos, usa el método peek() para recuperar datos de forma más eficiente, como se muestra en la 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 pequeña y aleatoria de datos mientras usas el modo de ordenamiento parcial.

Difiere 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 head() que recupera los datos reales. Esta recuperación puede ralentizar el proceso iterativo de programació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 a peek() y head().

¿Qué sigue?