Otimizar a performance dos DataFrames do BigQuery

O BigQuery DataFrames ajuda você a analisar e transformar dados no BigQuery usando uma API compatível com pandas. Para tornar o processamento de dados mais rápido e econômico, use várias técnicas para melhorar a performance.

Este documento descreve as seguintes maneiras de otimizar a performance:

Usar o modo de ordenação parcial

O BigQuery DataFrames tem um recurso de modo de ordenação que impõe uma ordem de linha específica para operações como funções de janela e junções. É possível especificar o modo de ordenação definindo a propriedade ordering_mode como strict (conhecido como modo de ordenação estrita, que é o padrão) ou partial (conhecido como modo de ordenação parcial). Usar a configuração partial pode tornar suas consultas mais eficientes.

O modo de ordenação parcial é diferente do modo de ordenação estrita. O modo de ordenação estrita organiza todas as linhas em uma ordem específica. Essa ordenação total faz com que os DataFrames do BigQuery funcionem melhor com o pandas, permitindo que você acesse as linhas por ordem usando a propriedade DataFrame.iloc. No entanto, a ordenação total e o índice sequencial padrão impedem que os filtros em colunas ou linhas reduzam a quantidade de dados verificados. Essa prevenção só não ocorre se você aplicar esses filtros como parâmetros às funções read_gbq e read_gbq_table. Para ordenar todas as linhas no DataFrame, os DataFrames do BigQuery criam um hash de todas as linhas. Essa operação pode causar uma verificação completa de dados que ignora os filtros de linha e coluna.

O modo de ordenação parcial impede que os DataFrames do BigQuery criem uma ordenação total para todas as linhas e desativa recursos que precisam de uma ordenação total, como a propriedade DataFrame.iloc. O modo de ordenação parcial também define a classe DefaultIndexKind como um índice nulo, em vez de um índice sequencial.

Ao filtrar um objeto DataFrame usando o modo de ordenação parcial, o DataFrames do BigQuery não calcula quais linhas estão faltando no índice sequencial. O modo de ordenação parcial também não combina dados automaticamente com base no índice. Essas abordagens podem aumentar a eficiência das suas consultas. No entanto, seja qual for o modo de ordenação usado (padrão estrito ou parcial), a API BigQuery DataFrames funciona como a API pandas.

Nos modos de ordenação parcial e estrita, você paga pelos recursos do BigQuery que usa. No entanto, usar o modo de ordenação parcial pode reduzir os custos ao trabalhar com tabelas grandes em cluster e particionadas. Essa redução de custo ocorre porque os filtros de linha em colunas de cluster e partição reduzem a quantidade de dados processados.

Ativar o modo de ordenação parcial

Para usar a ordenação parcial, defina a propriedade ordering_mode como partial antes de realizar qualquer outra operação com o BigQuery DataFrames, conforme mostrado no exemplo de código a seguir:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

O modo de ordenação parcial impede junções implícitas de objetos BigQuery DataFrames não relacionados porque não tem um índice sequencial. Em vez disso, chame explicitamente o método DataFrame.merge para unir dois objetos do BigQuery DataFrames que derivam de expressões de tabela diferentes.

Os recursos Series.unique() e Series.drop_duplicates() não funcionam com o modo de ordenação parcial. Em vez disso, use o método groupby para encontrar valores únicos, conforme mostrado no exemplo a seguir:

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

Com o modo de ordenação parcial, a saída das funções DataFrame.head(n) e Series.head(n) pode não ser a mesma sempre que você as executa. Para baixar uma pequena amostra aleatória dos dados, use os métodos DataFrame.peek() ou Series.peek().

Para um tutorial detalhado em que você usa a propriedade ordering_mode = "partial", consulte Como analisar downloads de pacotes do PyPI com o BigQuery DataFrames.

Solução de problemas

Como os DataFrames do BigQuery no modo de ordenação parcial às vezes não têm uma ordenação ou um índice, você pode encontrar os seguintes problemas ao usar alguns métodos compatíveis com pandas.

Erro de pedido obrigatório

Alguns recursos, como as funções DataFrame.head() e DataFrame.iloc, precisam de uma ordenação. Para uma lista de recursos que exigem ordenação, consulte a coluna Requer ordenação em APIs pandas compatíveis.

Quando um objeto não tem ordenação, a operação falha com uma mensagem OrderRequiredError como esta: OrderRequiredError: Op iloc requires an ordering. Use .sort_values or .sort_index to provide an ordering.

Como a mensagem de erro afirma, é possível fornecer uma ordenação usando o método DataFrame.sort_values() para classificar por uma ou mais colunas. Outros métodos, como DataFrame.groupby(), fornecem implicitamente uma ordenação total com base nas chaves de agrupamento.

Se a ordenação não for totalmente estável para todas as linhas, as operações posteriores poderão mostrar uma mensagem AmbiguousWindowWarning como esta: AmbiguousWindowWarning: Window ordering may be ambiguous, this can cause unstable results.

Se o seu trabalho puder lidar com resultados que nem sempre são os mesmos ou se você puder verificar manualmente se a ordenação é total, filtre a mensagem AmbiguousWindowWarning desta forma:

import warnings

import bigframes.exceptions

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

Erro de índice nulo

Alguns recursos, como as propriedades DataFrame.unstack() e Series.interpolate(), precisam de um índice. Para uma lista de recursos que exigem um índice, consulte a coluna Requer índice em APIs pandas compatíveis.

Quando você usa uma operação que exige um índice com modo de ordenação parcial, a operação gera uma mensagem NullIndexError como esta: NullIndexError: DataFrame cannot perform interpolate as it has no index. Set an index using set_index.

Como a mensagem de erro afirma, é possível fornecer um índice usando o método DataFrame.set_index() para classificar por uma ou mais colunas. Outros métodos, como DataFrame.groupby(), fornecem implicitamente um índice com base nas chaves de agrupamento, a menos que o parâmetro as_index=False seja definido.

Armazenar em cache os resultados após operações dispendiosas

O DataFrames do BigQuery armazena operações localmente e adia a execução de consultas até que determinadas condições sejam atendidas. Isso pode fazer com que as mesmas operações sejam executadas várias vezes em consultas diferentes.

Para evitar a repetição de operações caras, salve os resultados intermediários com o método cache(), conforme mostrado no exemplo a seguir:

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

Esse método cria uma tabela temporária do BigQuery para armazenar seus resultados. A cobrança é feita pelo armazenamento dessa tabela temporária no BigQuery.

Visualizar seus dados com o método peek()

O BigQuery DataFrames oferece dois métodos de API para visualizar dados:

  • peek(n) retorna n linhas de dados, em que n é o número de linhas.
  • head(n) retorna as primeiras n linhas de dados, dependendo do contexto, em que n é o número de linhas.

Use o método head() somente quando a ordem dos dados for importante, por exemplo, quando você quiser os cinco maiores valores em uma coluna. Em outros casos, use o método peek() para uma recuperação de dados mais eficiente, conforme mostrado no exemplo de código a seguir:

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)

Também é possível usar o método peek() para baixar uma pequena amostra aleatória de dados ao usar o modo de ordenação parcial.

Adiar a recuperação de dados do repr()

É possível chamar o método repr() nos DataFrames do BigQuery com notebooks ou o depurador do seu ambiente de desenvolvimento integrado. Essa chamada aciona a chamada head() que recupera os dados reais. Essa recuperação pode deixar mais lento o processo iterativo de programação e depuração, além de gerar custos.

Para evitar que o método repr() recupere dados, defina o atributo repr_mode como "deferred", conforme mostrado no exemplo a seguir:

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

No modo adiado, só é possível visualizar os dados com chamadas peek() e head() explícitas.

A seguir