Escribir eficientemente un dataframe de Pandas en Google BigQuery

Estoy intentando cargar una consulta grande de pandas.DataFrame en Google utilizando la función pandas.DataFrame.to_gbq() documentada aquí . El problema es que to_gbq() tarda 2.3 minutos, mientras que la carga directa a Google Cloud Storage GUI demora menos de un minuto. Estoy planeando subir un montón de marcos de datos (~ 32) cada uno con un tamaño similar, así que quiero saber cuál es la alternativa más rápida.

Este es el script que estoy usando:

 dataframe.to_gbq('my_dataset.my_table', 'my_project_id', chunksize=None, # i've tryed with several chunksizes, it runs faster when is one big chunk (at least for me) if_exists='append', verbose=False ) dataframe.to_csv(str(month) + '_file.csv') # the file size its 37.3 MB, this takes almost 2 seconds # manually upload the file into GCS GUI print(dataframe.shape) (363364, 21) 

Mi pregunta es, ¿qué es más rápido?

  1. Cargue Dataframe usando la función pandas.DataFrame.to_gbq()
  2. Guardando Dataframe como csv y luego cárguelo como un archivo a BigQuery utilizando la API de Python
  3. Guardando Dataframe como csv y luego cargue el archivo en Google Cloud Storage mediante este procedimiento y luego léalo desde BigQuery

actualizar:

la alternativa 2, usando pd.DataFrame.to_csv() y load_data_from_file() parece tomar más tiempo que la alternativa 1 (17.9 segundos más en promedio con 3 bucles):

 def load_data_from_file(dataset_id, table_id, source_file_name): bigquery_client = bigquery.Client() dataset_ref = bigquery_client.dataset(dataset_id) table_ref = dataset_ref.table(table_id) with open(source_file_name, 'rb') as source_file: # This example uses CSV, but you can use other formats. # See https://cloud.google.com/bigquery/loading-data job_config = bigquery.LoadJobConfig() job_config.source_format = 'text/csv' job_config.autodetect=True job = bigquery_client.load_table_from_file( source_file, table_ref, job_config=job_config) job.result() # Waits for job to complete print('Loaded {} rows into {}:{}.'.format( job.output_rows, dataset_id, table_id)) 

¡gracias!

Hice la comparación de las alternativas 1 y 3 en Datalab usando el siguiente código:

 from datalab.context import Context import datalab.storage as storage import datalab.bigquery as bq import pandas as pd from pandas import DataFrame import time # Dataframe to write my_data = [{1,2,3}] for i in range(0,100000): my_data.append({1,2,3}) not_so_simple_dataframe = pd.DataFrame(data=my_data,columns=['a','b','c']) #Alternative 1 start = time.time() not_so_simple_dataframe.to_gbq('TestDataSet.TestTable', Context.default().project_id, chunksize=10000, if_exists='append', verbose=False ) end = time.time() print("time alternative 1 " + str(end - start)) #Alternative 3 start = time.time() sample_bucket_name = Context.default().project_id + '-datalab-example' sample_bucket_path = 'gs://' + sample_bucket_name sample_bucket_object = sample_bucket_path + '/Hello.txt' bigquery_dataset_name = 'TestDataSet' bigquery_table_name = 'TestTable' # Define storage bucket sample_bucket = storage.Bucket(sample_bucket_name) # Create or overwrite the existing table if it exists table_schema = bq.Schema.from_dataframe(not_so_simple_dataframe) # Write the DataFrame to GCS (Google Cloud Storage) %storage write --variable not_so_simple_dataframe --object $sample_bucket_object # Write the DataFrame to a BigQuery table table.insert_data(not_so_simple_dataframe) end = time.time() print("time alternative 3 " + str(end - start)) 

y aquí están los resultados para n = {10000,100000,1000000}:

 n alternative_1 alternative_3 10000 30.72s 8.14s 100000 162.43s 70.64s 1000000 1473.57s 688.59s 

A juzgar por los resultados, la alternativa 3 es más rápida que la alternativa 1.