Ottimizzare le prestazioni di BigQuery DataFrames

BigQuery DataFrames ti aiuta ad analizzare e trasformare i dati in BigQuery utilizzando un'API compatibile con pandas. Per rendere l'elaborazione dei dati più rapida ed economica, puoi utilizzare diverse tecniche per migliorare le prestazioni.

Questo documento descrive i seguenti modi per ottimizzare le prestazioni:

Utilizzare la modalità di ordinamento parziale

BigQuery DataFrames ha una funzionalità di modalità di ordinamento che applica un ordine di riga specifico per operazioni come le funzioni finestra e i join. Puoi specificare la modalità di ordinamento impostando la proprietà ordering_mode su strict (nota come modalità di ordinamento rigoroso, che è l'impostazione predefinita) o partial (nota come modalità di ordinamento parziale). L'utilizzo dell'impostazione partial può rendere le query più efficienti.

La modalità di ordinamento parziale è diversa dalla modalità di ordinamento rigoroso. La modalità di ordinamento rigoroso dispone tutte le righe in un ordine specifico. Questo ordinamento totale fa sì che BigQuery DataFrames funzioni meglio con pandas, consentendoti di accedere alle righe in base al loro ordine utilizzando la proprietà DataFrame.iloc. Tuttavia, l'ordinamento totale e il relativo indice sequenziale predefinito impediscono ai filtri su colonne o righe di ridurre la quantità di dati scansionati. Questa prevenzione si verifica a meno che tu non applichi questi filtri come parametri alle funzioni read_gbq e read_gbq_table. Per ordinare tutte le righe nel DataFrame, BigQuery DataFrames crea un hash di tutte le righe. Questa operazione può causare una scansione completa dei dati che ignora i filtri di riga e colonna.

La modalità di ordinamento parziale impedisce a BigQuery DataFrames di creare un ordine totale per tutte le righe e disattiva le funzionalità che richiedono un ordine totale, come la proprietà DataFrame.iloc. La modalità di ordinamento parziale imposta anche la DefaultIndexKind classe su un indice nullo, anziché su un indice sequenziale.

Quando filtri un oggetto DataFrame utilizzando la modalità di ordinamento parziale, BigQuery DataFrames non calcola le righe mancanti nell'indice sequenziale. Inoltre, la modalità di ordinamento parziale non combina automaticamente i dati in base all'indice. Questi approcci possono aumentare l'efficienza delle query. Tuttavia, indipendentemente dal fatto che tu utilizzi la modalità di ordinamento rigoroso predefinita o la modalità di ordinamento parziale, l'API BigQuery DataFrames funziona come la nota API pandas.

Con entrambe le modalità di ordinamento parziale e rigoroso, paghi per le risorse BigQuery che utilizzi. Tuttavia, l'utilizzo della modalità di ordinamento parziale può ridurre i costi quando si lavora con tabelle partizionate e in cluster di grandi dimensioni. Questa riduzione dei costi si verifica perché i filtri di riga sulle colonne di cluster e partizione riducono la quantità di dati elaborati.

Attivare la modalità di ordinamento parziale

Per utilizzare l'ordinamento parziale, imposta la proprietà ordering_mode su partial prima di eseguire qualsiasi altra operazione con BigQuery DataFrames, come mostrato nel seguente esempio di codice:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

La modalità di ordinamento parziale impedisce i join impliciti di oggetti BigQuery DataFrames non correlati perché non ha un indice sequenziale. Devi invece chiamare esplicitamente il metodo DataFrame.merge per unire due oggetti BigQuery DataFrames derivati da espressioni di tabella diverse.

Le funzionalità Series.unique() e Series.drop_duplicates() non funzionano con la modalità di ordinamento parziale. Utilizza invece il metodo groupby per trovare valori univoci, come mostrato nell'esempio seguente:

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

Con la modalità di ordinamento parziale, l'output delle funzioni DataFrame.head(n) e Series.head(n) potrebbe non essere lo stesso ogni volta che le esegui. Per scaricare un piccolo campione casuale dei dati, utilizza i DataFrame.peek() o Series.peek() metodi.

Per un tutorial dettagliato in cui utilizzi la ordering_mode = "partial" proprietà, consulta Analizzare i download di pacchetti da PyPI con BigQuery DataFrames.

Risoluzione dei problemi

Poiché BigQuery DataFrames in modalità di ordinamento parziale a volte non ha un ordinamento o un indice, potresti riscontrare i seguenti problemi quando utilizzi alcuni metodi compatibili con pandas.

Errore di ordinamento obbligatorio

Alcune funzionalità, come le funzioni DataFrame.head() e DataFrame.iloc, richiedono un ordinamento. Per un elenco delle funzionalità che richiedono l'ordinamento, consulta la colonna Richiede ordinamento in API pandas supportate.

Quando un oggetto non ha un ordinamento, l'operazione non riesce e viene visualizzato un messaggio OrderRequiredError simile al seguente: OrderRequiredError: Op iloc requires an ordering. Use .sort_values or .sort_index to provide an ordering.

Come indicato nel messaggio di errore, puoi fornire un ordinamento utilizzando il DataFrame.sort_values() metodo per ordinare in base a una o più colonne. Altri metodi, come DataFrame.groupby(), forniscono implicitamente un ordinamento totale basato sulle chiavi di raggruppamento.

A differenza di pandas, se utilizzi la modalità di ordinamento parziale, l'esecuzione dello stesso codice potrebbe produrre risultati diversi ogni volta che lo esegui. Per garantire risultati coerenti, utilizza un ordinamento totale stabile per tutte le righe.

Errore di indice nullo

Alcune funzionalità, come le proprietà DataFrame.unstack() e Series.interpolate(), richiedono un indice. Per un elenco delle funzionalità che richiedono un indice, consulta la colonna Richiede indice in API pandas supportate.

Quando utilizzi un'operazione che richiede un indice con la modalità di ordinamento parziale, l'operazione genera un messaggio NullIndexError simile al seguente: NullIndexError: DataFrame cannot perform interpolate as it has no index. Set an index using set_index.

Come indicato nel messaggio di errore, puoi fornire un indice utilizzando il DataFrame.set_index() metodo per ordinare in base a una o più colonne. Altri metodi, come DataFrame.groupby(), forniscono implicitamente un indice basato sulle chiavi di raggruppamento, a meno che non sia impostato il parametro as_index=False.

Memorizzare nella cache i risultati dopo operazioni costose

BigQuery DataFrames archivia le operazioni localmente e posticipa l'esecuzione delle query fino a quando non vengono soddisfatte determinate condizioni. In questo modo, le stesse operazioni possono essere eseguite più volte in query diverse.

Per evitare di ripetere operazioni costose, salva i risultati intermedi con il metodo cache(), come mostrato nell'esempio seguente:

# 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))

Questo metodo crea una tabella BigQuery temporanea per archiviare i risultati. Ti viene addebitato l'utilizzo dello spazio di archiviazione di questa tabella temporanea in BigQuery.

Visualizzare l'anteprima dei dati con il metodo peek()

BigQuery DataFrames offre due metodi API per visualizzare l'anteprima dei dati:

  • peek(n) restituisce n righe di dati, dove n è il numero di righe.
  • head(n) restituisce le prime n righe di dati, a seconda del contesto, dove n è il numero di righe.

Utilizza il metodo head() solo quando l'ordine dei dati è importante, ad esempio quando vuoi i cinque valori più grandi in una colonna. In altri casi, utilizza il metodo peek() per un recupero dei dati più efficiente, come mostrato nel seguente esempio di codice:

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)

Puoi anche utilizzare il metodo peek() per scaricare un piccolo campione casuale di dati utilizzando la modalità di ordinamento parziale.

Posticipare il recupero dei dati repr()

Puoi chiamare il repr() metodo in BigQuery DataFrames con blocchi note o il debugger IDE. Questa chiamata attiva la chiamata head() che recupera i dati effettivi. Questo recupero può rallentare il processo di codifica e debug iterativo e comportare costi.

Per impedire al metodo repr() di recuperare i dati, imposta l'attributo repr_mode su "deferred", come mostrato nell'esempio seguente:

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

In modalità posticipata, puoi visualizzare l'anteprima dei dati solo con chiamate esplicite peek() e head() calls.

Passaggi successivi