Эффективно написать кадр данных Pandas в Google BigQuery
Я пытаюсь загрузить pandas.DataFrame
Google большой запрос, используя pandas.DataFrame.to_gbq()
Функция документирована здесь. Проблема в том, что to_gbq()
занимает 2,3 минуты, а загрузка непосредственно в Google Cloud Storage GUI занимает меньше минуты. Я планирую загрузить несколько фреймов данных (~32), каждый из которых имеет одинаковый размер, поэтому я хочу знать, что является более быстрой альтернативой.
Это скрипт, который я использую:
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)
мой вопрос, что быстрее?
- Загрузить
Dataframe
с помощьюpandas.DataFrame.to_gbq()
функция - экономия
Dataframe
как CSV, а затем загрузить в виде файла в BigQuery с помощью Python API - экономия
Dataframe
как csv, а затем загрузите файл в Google Cloud Storage, используя эту процедуру, а затем прочитайте его из BigQuery
Обновить:
альтернатива 2, используя pd.DataFrame.to_csv()
а также load_data_from_file()
кажется, занимает больше времени, чем альтернатива 1 (в среднем на 17,9 с больше с 3 циклами):
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))
благодарю вас!
3 ответа
Я сделал сравнение для варианта 1 и 3 в Datalab
используя следующий код:
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))
и вот результаты для n = {10000,100000,1000000}:
n alternative_1 alternative_3
10000 30.72s 8.14s
100000 162.43s 70.64s
1000000 1473.57s 688.59s
Судя по результатам, вариант 3 быстрее, чем вариант 1.
У меня также были проблемы с производительностью с to_gbq(), я просто попробовал собственный клиент Google, и он на много миль быстрее (примерно в 4 раза), и если вы пропустите шаг, на котором вы ждете результата, он будет примерно в 20 раз быстрее.
Стоит отметить, что лучше всего дождаться результата и проверить его, но в моем случае позже есть дополнительные шаги, которые подтверждают результаты.
Я использую pandas_gbq версии 0.15 (последняя на момент написания). Попробуй это:
from google.cloud import bigquery
import pandas
df = pandas.DataFrame(
{
'my_string': ['a', 'b', 'c'],
'my_int64': [1, 2, 3],
'my_float64': [4.0, 5.0, 6.0],
'my_timestamp': [
pandas.Timestamp("1998-09-04T16:03:14"),
pandas.Timestamp("2010-09-13T12:03:45"),
pandas.Timestamp("2015-10-02T16:00:00")
],
}
)
client = bigquery.Client()
table_id = 'my_dataset.new_table'
# Since string columns use the "object" dtype, pass in a (partial) schema
# to ensure the correct BigQuery data type.
job_config = bigquery.LoadJobConfig(schema=[
bigquery.SchemaField("my_string", "STRING"),
])
job = client.load_table_from_dataframe(
df, table_id, job_config=job_config
)
# Wait for the load job to complete. (I omit this step)
# job.result()