¿Qué es BigQuery?
Una de las ventajas de usar Google Cloud Platform (GCP) es tener a su disposición BigQuery. La solución de almacenamiento de datos en la nube de Google.
BigQuery brinda a los usuarios de GCP acceso a las características clave de Dremel. La solución de almacenamiento de datos interna propia de Google. Bajo el capó, Dremel almacena los datos en formato de columnas y utiliza una arquitectura de árbol para paralelizar las consultas en miles de máquinas. Y cada consulta explora toda la tabla.
Entonces, ¿qué tiene eso de bueno?
Con BigQuery puede ejecutar consultas SQL en una tabla con miles de millones de filas y obtener los resultados en segundos. Aunque miles de máquinas de Google procesan los datos. Cada consulta solo ocupa una pequeña cantidad de tiempo de cómputo.
Por lo que solo cuesta $ 5.00 por TB de datos procesados. Lo mejor de todo es que Google se encarga de la administración de la infraestructura.
Las consultas que solían tomar horas o más en las bases de datos tradicionales ahora se pueden procesar en cuestión de segundos. Esto permite a los analistas responder rápidamente a preguntas de negocios, crear paneles de control sobre datos agregados, etc.
¿Qué pasa con BigQuery y Data Science?
Entonces, si sus datos se encuentran ahora en un almacén de datos de BigQuery, ¿acelera la ciencia de datos? La respuesta es, depende. Si bien BigQuery es bueno para consultar grandes cantidades de datos, el procesamiento y la transformación de los datos se limita a funciones básicas similares a SQL.
El procesamiento complejo de datos tendrá que hacerse fuera de BigQuery, lo que nos lleva al siguiente problema; sacar datos de BigQuery es lento. Específicamente, mover los datos a un marco de datos pandas o R es lento.
Usted comienza a notar esto cuando trabaja con cientos de miles de filas o más. En Python, la biblioteca de Google google-cloud-bigquery y la biblioteca de la comunidad pandas-gbq permiten a los usuarios transferir el resultado de BigQuery a los pandas. Ambos enfrentan problemas de transferencia de datos, como se destaca en este GitHub número .
Por ejemplo, ejecutando datos de consulta del conjunto de datos público del New York Yellow Taxi 2018 que devuelve 2 millones de líneas solo de 63 millones toma 18 segundos en BigQuery:
from google.cloud import bigquery as bq
import time
import gcsfs
import pandas as pd
client = bq.Client()
taxi_query="""
#standardSQL
SELECT *
FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2018`
LIMIT 2000000
"""
job_config = bq.QueryJobConfig()
now=time.time()
query_job=client.query(taxi_query,location='US')
res=query_job.result()
print('query took:',round(time.time()-now,2),'s')
Sin embargo, cargar el resultado en un marco de datos de pandas a través del to_dataframe (), lleva casi 6 minutos:
now=time.time()
yellow_taxi=res.to_dataframe()
print('load to pandas from BQ took:',round(time.time()-now,2),'s')
Puede ser frustrante esperar minutos para cargar el resultado en pandas cuando la consulta solo tomó segundos. En algunos casos, el científico de datos tiene acceso tanto a la base de datos tradicional de SQL como a las tablas de BigQuery, y obtener datos de la base de datos tradicional de SQL en pandas puede ser más rápido, ya que en primer lugar no había tantos datos para analizar.
En R, el paquete bigquery también enfrenta el mismo problema de transferencia de datos, aunque es más rápido ya que el sistema para descargar datos ha sido escrito para mejorar el rendimiento .
BigQuery: Soluciones provisionales
Hay algunas formas de solucionar esto, dependiendo de si está realizando exploraciones o construyendo tuberías de aprendizaje automático de producción.
Exploratorio
Por lo general, cuando comienzan a trabajar en un nuevo conjunto de datos. Los científicos de datos utilizan los cuadernos de Jupyter para explorar rápidamente los datos y construirlos. modelos preliminares. Se pueden realizar y refinar varias llamadas de BigQuery a medida que se exploran los datos.
1. Limitar el tamaño de la consulta
La solución más sencilla es limitar el resultado de la consulta, ya sea limitando el número de filas devueltas o filtrando y agregando los resultados para reducir la cantidad de datos que se transfieren.
BigQuery no está realmente destinado a transferir grandes cantidades de datos de todos modos. Sin embargo, esto depende de la cantidad de columnas que tenga y en la era de big data. Es posible que no obtenga una muestra representativa de su conjunto de datos.
2. Dump to csv
¡Escribir el resultado de la consulta en csv primero y luego leer el resultado de csv en pandas puede acelerar las cosas, hasta 10 veces! Para ser exactos, debido a las peculiaridades de la API, primero debe exportar el resultado de la consulta a una tabla y luego exportar la tabla a csv en un cubo de almacenamiento en la nube.
De esta manera, es posible consultar los datos solo una vez y luego leerlos desde su almacenamiento, lo que le brinda resultados repetibles. Este método es un poco torpe y hay algunos gastos generales para administrar las diferentes salidas, cubos y tablas de csv.
Usando este método, escribir en csv en un cubo de almacenamiento y leer desde csv solo toma alrededor de medio minuto cada uno:
Exportación a GCS:
##Export to GCS
now=time.time()
destination_uri = "gs://david-us/*taxi2018.csv"
dataset_ref = client.dataset("taxi_us", project=project)
table_ref = dataset_ref.table("2018")
extract_job = client.extract_table(
table_ref,
destination_uri)
extract_job.result() # Waits for job to complete
print('create table and write to GCS took:',round(time.time()-now,2),'s')
Leer de GCS :
now=time.time()
gcs = gcsfs.GCSFileSystem(project=project)
destination_uri = "gs://david-us/*taxi2018.csv"
files=gcs.glob(destination_uri)
df = pd.concat([pd.read_csv('gs://'+f) for f in files], ignore_index=True)
print('read csv took:',round(time.time()-now,2),'s')
Mientras escribía esto, Google lanzó la versión beta de BigQuery Storage que permite un acceso rápido a los datos de BigQuery y, por lo tanto, una descarga más rápida a los pandas.
Esta parece ser una solución ideal si desea importar la tabla ENTERA a pandas o ejecutar filtros simples. Sin embargo, la desventaja es que las consultas de tipo SQL ya no funcionan.
Las columnas se pueden seleccionar mientras que las filas se pueden filtrar, pero solo comparando una columna con un valor constante. Si necesita muestrear los datos, debe confiar en el filtrado por un valor en una columna.
En el siguiente ejemplo, probamos la API de almacenamiento de BigQuery.
Como las declaraciones tipo SQL no funcionan, filtramos el pickup_location_id a “48” para obtener alrededor de 2 millones de filas a cambio.
Llevar los datos a pandas tomó aproximadamente 100 segundos, más rápido que cargar directamente desde BigQuery pero más lento que descargar en csv.
import google.auth
from google.cloud import bigquery
from google.cloud import bigquery_storage_v1beta1
import fastavro
credentials, your_project_id = google.auth.default(
scopes=["https://www.googleapis.com/auth/cloud-platform"]
)
# Make clients.
bqclient = bigquery.Client(
credentials=credentials,
project=project
)
bqstorageclient = bigquery_storage_v1beta1.BigQueryStorageClient(
credentials=credentials
)
table = bigquery_storage_v1beta1.types.TableReference()
table.project_id = "bigquery-public-data"
table.dataset_id = "new_york_taxi_trips"
table.table_id = "tlc_yellow_trips_2018"
# Select columns to read
# Limit rows to PICK UP ID==48
read_options = bigquery_storage_v1beta1.types.TableReadOptions()
read_options.row_restriction = 'pickup_location_id = "48"'
read_options.selected_fields.append("vendor_id")
read_options.selected_fields.append("passenger_count")
read_options.selected_fields.append("trip_distance")
read_options.selected_fields.append("rate_code")
read_options.selected_fields.append("store_and_fwd_flag")
read_options.selected_fields.append("payment_type")
read_options.selected_fields.append("fare_amount")
read_options.selected_fields.append("extra")
read_options.selected_fields.append("mta_tax")
read_options.selected_fields.append("tip_amount")
read_options.selected_fields.append("tolls_amount")
read_options.selected_fields.append("imp_surcharge")
read_options.selected_fields.append("total_amount")
read_options.selected_fields.append("pickup_location_id")
read_options.selected_fields.append("dropoff_location_id")
parent = "projects/{}".format(your_project_id)
session = bqstorageclient.create_read_session(
table, parent, read_options=read_options
)
now=time.time()
# This example reads from only a single stream. Read from multiple streams
# to fetch data faster. Note that the session may not contain any streams
# if there are no rows to read.
stream = session.streams[0]
position = bigquery_storage_v1beta1.types.StreamPosition(stream=stream)
reader = bqstorageclient.read_rows(position)
# Parse all Avro blocks and create a dataframe. This call requires a
# session, because the session contains the schema for the row blocks.
bq_storage = reader.to_dataframe(session)
print("Time Taken With BigQuery Storage:",round(time.time()-now,2),'s')
Sin embargo, con BigQuery Storage existe la posibilidad de lectura en los datos con múltiples flujos, aumentando la velocidad de transferencia.
4. BigQuery ML
BigQuery ML es un esfuerzo de Google para permitir que los usuarios de BigQuery construyan modelos de aprendizaje automático mediante consultas SQL.
En lugar de sacar los datos de BigQuery y luego construir un modelo, el modelo se lleva a los datos. Si bien el objetivo es que todo se haga en BigQuery. Encuentro que la solución es muy limitada ya que las transformaciones de datos complejas no se pueden realizar con SQL y solo están disponibles los modelos de regresión lineal y logística.
Producción
En producción, una parte significativa de Los datos tendrán que ser procesados y se necesitan soluciones robustas. Si bien BigQuery Storage podría ser una solución para ejecutar en pandas en producción. Probablemente sería mejor evitar pandas por completo debido a problemas de rendimiento y construir tuberías de procesamiento más robustas.
1. TensorFlow
BigQuery almacena datos estructurados. ¿Por qué TensorFlow? En realidad, el marco TensorFlow puede manejar datos estructurados también con modelos como regresión lineal, regresión logística, árboles reforzados, etc. La clase BigQueryReader permite que Tensorflow acceda a BigQuery.
2. Spark
Al igual que Tensorflow, BigQuery también tiene conectores para Spark, lo que permite el uso de bibliotecas como Sparkling Water de H2O.ai. Desafortunadamente, si está utilizando pyspark, los datos deberán ser volcados a Cloud Storage antes de que Spark pueda leerlos.
Conclusión
Si bien BigQuery permite consultas rápidas con sintaxis SQL. La extracción de datos para la ciencia de datos puede tedioso. Si la limitación del tamaño de la consulta no me funciona. Personalmente prefiero volcar a CSV y leer desde allí ya que permite un análisis repetible.
Mejoras adicionales en la biblioteca google-cloud-bigquery ser una interfaz para Spark / Dask para la lectura perezosa de datos. Así como la capacidad de escribir transformaciones similares a dplyr de los datos en lugar de escribir consultas SQL para acceder a datos en BigQuery.
Enlaces:
- Google Cloud BigQuery
- Google Driven google-cloud-bigquery biblioteca de python
- Community Driven pandas-gbq ]
- Google BigQuery Storage (Beta) reference
- BigQuery ML reference
- Big Query Rep. Google Cloud Dataproc Big Query Connector
- documentación
- Anuncio de Bidquery 1.0.0 de Tidyverse