El libro “Google BigQuery. Todo sobre almacenamiento de datos, análisis y aprendizaje automático "

imagen¡Hola habitantes! ¿Está intimidado por la necesidad de procesar conjuntos de datos de petabytes? Conozca Google BigQuery, un sistema de almacenamiento de información que puede consolidar datos en toda la empresa, facilitar el análisis interactivo y habilitar el aprendizaje automático. Ahora puede almacenar, consultar, recuperar y explorar datos de manera eficiente en un entorno conveniente. Walyappa Lakshmanan y Jordan Taijani le enseñarán cómo trabajar en un almacén de datos moderno utilizando todo el poder de una nube pública escalable y sin servidor. Con este libro, podrá: - Profundizar en los aspectos internos de BigQuery - Explorar los tipos de datos, las funciones y los operadores que admite Big Query - Optimizar consultas e implementar esquemas para mejorar el rendimiento o reducir costos - Aprender sobre GIS, viajes en el tiempo, DDL / DML.funciones personalizadas y scripts SQL - Resuelva muchos desafíos de aprendizaje automático - Aprenda a proteger los datos, realizar un seguimiento del rendimiento y autenticar a los usuarios.





Minimizar los costos de red BigQuery es un servicio regional que está disponible en todo el mundo. Por ejemplo, si solicita un conjunto de datos almacenado en la región de la UE, la solicitud se ejecutará en servidores ubicados en un centro de datos de la Unión Europea. Para que pueda almacenar los resultados de la consulta en una tabla, debe estar en un conjunto de datos que también se encuentre en la región de la UE. Sin embargo, se puede llamar a la API de REST de BigQuery (es decir, ejecutar una consulta) desde cualquier parte del mundo, incluso desde computadoras fuera de GCP. Cuando se trabaja con otros recursos de GCP, como Google Cloud Storage o Cloud Pub / Sub, se obtiene el mejor rendimiento si se encuentran en la misma región que el conjunto de datos. Por lo tanto, si la solicitud se ejecuta desde una instancia de Compute Engine o un clúster de Cloud Dataproc, la sobrecarga de la red será mínima.si la instancia o el clúster también se encuentra en la misma región que el conjunto de datos solicitado. Al acceder a BigQuery desde fuera de GCP, considere la topología de su red e intente minimizar la cantidad de saltos entre la computadora cliente y el centro de GCP donde reside el conjunto de datos.



Respuestas concisas e incompletas



Al acceder directamente a la API REST, la sobrecarga de la red se puede reducir aceptando respuestas concisas e incompletas. Para aceptar respuestas comprimidas, puede especificar en el encabezado HTTP que está listo para aceptar un archivo gzip y asegurarse de que la línea "gzip" aparezca en el encabezado User-Agent, por ejemplo:



Accept-Encoding: gzip
User-Agent: programName (gzip)


En este caso, todas las respuestas se comprimirán mediante gzip. De forma predeterminada, las respuestas de BigQuery contienen todos los campos que se enumeran en la documentación. Sin embargo, si sabemos qué parte de la respuesta nos interesa, podemos pedirle a BigQuery que envíe solo esa parte, reduciendo así la sobrecarga de la red. Por ejemplo, en este capítulo, vimos cómo obtener información completa sobre un trabajo usando la API de trabajos. Si solo está interesado en un subconjunto de la respuesta completa (por ejemplo, solo pasos en el plan de consulta), puede especificar los campos de interés para limitar el tamaño de la respuesta:



JOBSURL="https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs"
FIELDS="statistics(query(queryPlan(steps)))"
curl --silent \
    -H "Authorization: Bearer $access_token" \
    -H "Accept-Encoding: gzip" \
    -H "User-Agent: get_job_details (gzip)" \
    -X GET \
    "${JOBSURL}/${JOBID}?fields=${FIELDS}" \
| zcat


Tenga en cuenta que también establece que aceptamos datos comprimidos gzip.



Combinando múltiples solicitudes en paquetes



Cuando se usa la API REST, es posible combinar varias llamadas a la API de BigQuery con el tipo de contenido multiparte / mixto y solicitudes HTTP anidadas en cada parte. El cuerpo de cada parte especifica la operación HTTP (GET, PUT, etc.), la ruta a la URL, los encabezados y el cuerpo. En respuesta, el servidor enviará una única respuesta HTTP con el tipo de contenido multiparte / mixto, cada parte de la cual contendrá la respuesta (en orden) a la solicitud correspondiente en la solicitud por lotes. Aunque las respuestas se devuelven en un orden específico, el servidor puede procesar las llamadas en cualquier orden. Por lo tanto, una solicitud por lotes se puede considerar como un grupo de solicitudes ejecutadas en paralelo. Aquí hay un ejemplo de envío de una solicitud por lotes para obtener algunos detalles de los planes de ejecución de las últimas cinco solicitudes de nuestro proyecto. Primero usamos la herramienta de línea de comandos de BigQuery,para obtener las últimas cinco asignaciones exitosas:



# 5   
JOBS=$(bq ls -j -n 50 | grep SUCCESS | head -5 | awk '{print $1}')


La solicitud se envía al extremo de BigQuery para el procesamiento por lotes:



BATCHURL="https://www.googleapis.com/batch/bigquery/v2"
JOBSPATH="/projects/$PROJECT/jobs"
FIELDS="statistics(query(queryPlan(steps)))"


Puede definir solicitudes individuales en la ruta de la URL:



request=""
for JOBID in $JOBS; do
read -d '' part << EOF
--batch_part_starts_here
GET ${JOBSPATH}/${JOBID}?fields=${FIELDS}
EOF
request=$(echo "$request"; echo "$part")
done


Luego, puede enviar la solicitud como una solicitud compuesta:



curl --silent \
   -H "Authorization: Bearer $access_token" \
   -H "Content-Type: multipart/mixed; boundary=batch_part_starts_here" \
   -X POST \
   -d "$request" \
   "${BATCHURL}"


Lectura masiva con la API de almacenamiento de BigQuery



En el Capítulo 5, analizamos el uso de la API REST de BigQuery y las bibliotecas cliente para enumerar tablas y recuperar resultados de consultas. La API REST devuelve datos como registros paginados que son más adecuados para conjuntos de resultados relativamente pequeños. Sin embargo, con la llegada del aprendizaje automático y las herramientas distribuidas de extracción, transformación y carga (ETL), las herramientas externas ahora requieren un acceso masivo rápido y eficiente al repositorio administrado de BigQuery. Este acceso de lectura masiva se proporciona en la API de almacenamiento de BigQuery a través del protocolo de llamada a procedimiento remoto (RPC). Con la API de almacenamiento de BigQuery, los datos estructurados se transmiten a través de la red en un formato de serialización binario que se asemeja más al formato de almacenamiento de datos en columnas.Esto proporciona una paralelización adicional del conjunto de resultados en varios consumidores.



Los usuarios finales no usan la API de BigQuery Storage directamente. En su lugar, usan Cloud Dataflow, Cloud Dataproc, TensorFlow, AutoML y otras herramientas que usan la API de almacenamiento para leer datos directamente desde el almacenamiento administrado en lugar de a través de la API de BigQuery.



Debido a que la API de Storage accede a los datos almacenados directamente, el permiso para acceder a la API de BigQuery Storage es diferente de la API de BigQuery existente. Los permisos de la API de BigQuery Storage se deben configurar de forma independiente de los permisos de BigQuery.



La API de BigQuery Storage brinda varios beneficios a las herramientas que leen datos directamente desde el almacenamiento administrado de BigQuery. Por ejemplo, los consumidores pueden leer conjuntos de registros separados de una tabla utilizando varios subprocesos (por ejemplo, al permitir lecturas distribuidas de datos de diferentes servidores de producción en Cloud Dataproc), segmentar dinámicamente estos subprocesos (reduciendo así la latencia de cola, que puede ser un problema grave para los trabajos de MapReduce) , seleccione un subconjunto de columnas para leer (para pasar solo las características utilizadas por el modelo a las estructuras de aprendizaje automático), filtre los valores de las columnas (reduzca la cantidad de datos transmitidos a través de la red) y aún así garantice la consistencia de las instantáneas (es decir, la lectura de datos de un punto determinado en el tiempo).



En el Capítulo 5, cubrimos el uso de la extensión %% bigquery en Jupyter Notebook para cargar resultados de consultas en DataFrames. Sin embargo, los ejemplos utilizaron conjuntos de datos relativamente pequeños, desde una docena hasta varios cientos de registros. ¿Es posible cargar todo el conjunto de datos london_bicycles (24 millones de registros) en un DataFrame? Sí, puede, pero en este caso, debe usar la API de almacenamiento, no la API de BigQuery, para cargar datos en el DataFrame. Primero, debe instalar la biblioteca cliente Python de la API de almacenamiento con soporte para Avro y pandas. Esto se puede hacer con el comando



%pip install google-cloud-bigquery-storage[fastavro,pandas]


Luego, todo lo que queda es usar la extensión %% bigquery, como antes, pero agregue un parámetro que requiera que se use la API de almacenamiento:



%%bigquery df --use_bqstorage_api --project $PROJECT
SELECT 
   start_station_name 
   , end_station_name 
   , start_date 
   , duration
FROM `bigquery-public-data`.london_bicycles.cycle_hire


Tenga en cuenta que aquí estamos utilizando la capacidad de la API de almacenamiento para proporcionar acceso directo a columnas individuales; no es necesario leer toda la tabla de BigQuery en un DataFrame. Si la solicitud devuelve una pequeña cantidad de datos, la extensión usará automáticamente la API de BigQuery. Por tanto, no da miedo si siempre indicas esta bandera en las celdas del cuaderno. Para habilitar la marca --usebqstorageapi en todas las celdas del cuaderno, puede configurar la marca de contexto:



import google.cloud.bigquery.magics
google.cloud.bigquery.magics.context.use_bqstorage_api = True


Elegir un formato de almacenamiento eficiente



El rendimiento de una consulta depende de dónde y en qué formato se almacenan los datos que componen la tabla. En general, cuanto menos necesite la consulta para realizar búsquedas o conversiones de tipos, mejor será el rendimiento.



Fuentes de datos internas y externas



BigQuery admite la consulta de fuentes externas como Google Cloud Storage, Cloud Bigtable y Google Sheets, pero el mejor rendimiento de las consultas solo es posible cuando usa sus propias tablas.



Recomendamos usar BigQuery como un repositorio de datos analíticos para todos sus datos estructurados y semiestructurados. Las fuentes de datos externas se utilizan mejor para el almacenamiento provisional (Google Cloud Storage), cargas en vivo (Cloud Pub / Sub, Cloud Bigtable) o actualizaciones periódicas (Cloud SQL, Cloud Spanner). A continuación, configure su canalización de datos para cargar datos en un horario desde estas fuentes externas en BigQuery (consulte el Capítulo 4).



Si necesita solicitar datos de Google Cloud Storage, guárdelos en un formato de columnas comprimido (como Parquet) si es posible. Utilice formatos basados ​​en registros como JSON o CSV como último recurso.



Gestión del ciclo de vida del depósito de almacenamiento intermedio



Si carga datos a BigQuery después de colocarlos en Google Cloud Storage, asegúrese de eliminarlos de la nube después de la carga. Si usa la canalización ETL para cargar datos en BigQuery (para transformarlos significativamente o dejar solo una parte de los datos en el camino), es posible que desee guardar los datos originales en Google Cloud Storage. En tales casos, puede ayudar a reducir los costos mediante la definición de reglas de administración del ciclo de vida del depósito que degraden el almacenamiento en Google Cloud Storage.



A continuación, le mostramos cómo puede activar la gestión del ciclo de vida del depósito y configurar el movimiento automático de datos desde regiones federadas o clases estándar con más de 30 días de antigüedad a Nearline Storage, y datos almacenados en Nearline Storage durante más de 90 días a Coldline Storage:



gsutil lifecycle set lifecycle.yaml gs://some_bucket/


En este ejemplo, el archivo lifecycle.yaml contiene el siguiente código:



{
"lifecycle": {
  "rule": [
  {
   "action": {
    "type": "SetStorageClass",
    "storageClass": "NEARLINE"
   },
   "condition": {
    "age": 30,
    "matchesStorageClass": ["MULTI_REGIONAL", "STANDARD"]
   }
 },
 {
  "action": {
   "type": "SetStorageClass",
   "storageClass": "COLDLINE"
  },
  "condition": {
   "age": 90,
   "matchesStorageClass": ["NEARLINE"]
  }
 }
]}}


Puede utilizar la gestión del ciclo de vida no solo para cambiar la clase de un objeto, sino también para eliminar objetos que son más antiguos que un determinado umbral.



Almacenamiento de datos como matrices y estructuras



Además de otros conjuntos de datos disponibles públicamente, BigQuery tiene un conjunto de datos que contiene información sobre tormentas ciclónicas (huracanes, tifones, ciclones, etc.) de servicios meteorológicos de todo el mundo. Las tormentas ciclónicas pueden durar hasta varias semanas y sus parámetros meteorológicos se miden aproximadamente cada tres horas. Suponga que decide buscar en este conjunto de datos todas las tormentas que ocurrieron en 2018, la velocidad máxima del viento alcanzada por cada tormenta y la hora y ubicación de la tormenta cuando se alcanzó esa velocidad máxima. La siguiente consulta recupera toda esta información del conjunto de datos públicos:



SELECT
  sid, number, basin, name,
  ARRAY_AGG(STRUCT(iso_time, usa_latitude, usa_longitude, usa_wind) ORDER BY
usa_wind DESC LIMIT 1)[OFFSET(0)].*
FROM
  `bigquery-public-data`.noaa_hurricanes.hurricanes
WHERE
  season = '2018'
GROUP BY
  sid, number, basin, name
ORDER BY number ASC


La consulta recupera el identificador de tormenta (sid), sus estaciones, la piscina y el nombre de la tormenta (si está asignado) y luego encuentra una serie de observaciones realizadas para esa tormenta, clasifica las observaciones en orden descendente de velocidad del viento y elige la velocidad máxima para cada tormenta. ... Las tormentas en sí están ordenadas por número secuencial. El resultado incluye 88 registros y se parece a esto:





La solicitud tardó 1,4 segundos y procesó 41,7 MB. La primera entrada describe la tormenta Bolaven, que alcanzó una velocidad máxima de 29 m / s el 2 de enero de 2018 a las 18:00 UTC.



Dado que las observaciones las realizan varios servicios meteorológicos, estos datos se pueden estandarizar mediante campos anidados y almacenarse en BigQuery, como se muestra a continuación:



CREATE OR REPLACE TABLE ch07.hurricanes_nested AS

SELECT sid, season, number, basin, name, iso_time, nature, usa_sshs,
    STRUCT(usa_latitude AS latitude, usa_longitude AS longitude, usa_wind AS
wind, usa_pressure AS pressure) AS usa,
    STRUCT(tokyo_latitude AS latitude, tokyo_longitude AS longitude,
tokyo_wind AS wind, tokyo_pressure AS pressure) AS tokyo,
    ... AS cma,
    ... AS hko,
    ... AS newdelhi,
    ... AS reunion,
    ... bom,
    ... AS wellington,
    ... nadi
FROM `bigquery-public-data`.noaa_hurricanes.hurricanes


Las consultas de esta tabla tienen el mismo aspecto que las consultas de la tabla original, pero con un ligero cambio en los nombres de las columnas (usa.latitude en lugar de usa_latitude):



SELECT
  sid, number, basin, name,
  ARRAY_AGG(STRUCT(iso_time, usa.latitude, usa.longitude, usa.wind) ORDER BY
usa.wind DESC LIMIT 1)[OFFSET(0)].*
FROM
  ch07.hurricanes_nested
WHERE
  season = '2018'
GROUP BY
  sid, number, basin, name
ORDER BY number ASC


Esta solicitud procesa la misma cantidad de datos y se ejecuta en la misma cantidad de tiempo que la original, utilizando el conjunto de datos públicos. El uso de campos anidados (estructuras) no cambia la velocidad ni el costo de la consulta, pero puede hacer que la consulta sea más legible. Dado que hay muchas observaciones de la misma tormenta durante su duración, podemos cambiar el almacenamiento para que quepa en un registro el conjunto completo de observaciones para cada tormenta:



CREATE OR REPLACE TABLE ch07.hurricanes_nested_track AS

SELECT sid, season, number, basin, name,
 ARRAY_AGG(
   STRUCT(
    iso_time,
    nature,
    usa_sshs,
    STRUCT(usa_latitude AS latitude, usa_longitude AS longitude, usa_wind AS
wind, usa_pressure AS pressure) AS usa,
    STRUCT(tokyo_latitude AS latitude, tokyo_longitude AS longitude,
      tokyo_wind AS wind, tokyo_pressure AS pressure) AS tokyo,
    ... AS cma,
    ... AS hko,
    ... AS newdelhi,
    ... AS reunion,
    ... bom,
    ... AS wellington,
    ... nadi
  ) ORDER BY iso_time ASC ) AS obs
FROM `bigquery-public-data`.noaa_hurricanes.hurricanes
GROUP BY sid, season, number, basin, name


Tenga en cuenta que ahora almacenamos el sid, la estación y otras características de la tormenta como columnas escalares, porque no cambian dependiendo de su duración.



El resto de los datos, que cambian con cada observación, se almacena como una matriz de estructuras. Así es como se ve la consulta para la nueva tabla:



SELECT
  number, name, basin,
  (SELECT AS STRUCT iso_time, usa.latitude, usa.longitude, usa.wind
     FROM UNNEST(obs) ORDER BY usa.wind DESC LIMIT 1).*
FROM ch07.hurricanes_nested_track
WHERE season = '2018'
ORDER BY number ASC


Esta solicitud devolverá el mismo resultado, pero esta vez solo procesará 14,7 MB (una reducción de costes tres veces mayor) y se completará en un segundo (un aumento del 30% en la velocidad). ¿Qué causó esta mejora en el rendimiento? Cuando los datos se almacenan como una matriz, la cantidad de registros en la tabla cae drásticamente (de 682,000 a 14,000), 2 porque ahora solo hay un registro por tormenta, no muchos registros, uno para cada observación. Luego, cuando filtramos filas por temporada, BigQuery puede eliminar muchos casos relacionados al mismo tiempo, como se muestra en la Figura 1. 7.13.





Otra ventaja es que no es necesario duplicar registros de datos cuando se almacenan en la misma tabla casos con diferentes niveles de detalle. Una sola tabla puede almacenar datos de cambios de latitud y longitud para tormentas y datos de alto nivel como el nombre de la tormenta y la temporada. Y debido a que BigQuery almacena datos tabulares en columnas mediante compresión, puede consultar y procesar datos de alto nivel sin temor al costo de trabajar con datos detallados; ahora se almacenan como una matriz de valores separada para cada tormenta.



Por ejemplo, para averiguar la cantidad de tormentas por año, puede consultar solo las columnas requeridas:



WITH hurricane_detail AS (
SELECT sid, season, number, basin, name,
 ARRAY_AGG(
  STRUCT(
    iso_time,
    nature,
    usa_sshs,
    STRUCT(usa_latitude AS latitude, usa_longitude AS longitude, usa_wind AS
wind, usa_pressure AS pressure) AS usa,
    STRUCT(tokyo_latitude AS latitude, tokyo_longitude AS longitude,
        tokyo_wind
AS wind, tokyo_pressure AS pressure) AS tokyo
  ) ORDER BY iso_time ASC ) AS obs
FROM `bigquery-public-data`.noaa_hurricanes.hurricanes
GROUP BY sid, season, number, basin, name
)
SELECT
  COUNT(sid) AS count_of_storms,
  season
FROM hurricane_detail
GROUP BY season
ORDER BY season DESC


La solicitud anterior procesó 27 MB, que es la mitad de los 56 MB que tendrían que procesarse si no se usaran campos repetidos anidados.



Los campos anidados no mejoran el rendimiento por sí solos, aunque pueden mejorar la legibilidad al realizar una unión a otras tablas relacionadas. Además, los campos repetidos anidados son extremadamente útiles desde el punto de vista del rendimiento. Considere usar campos repetidos anidados en su esquema porque pueden aumentar drásticamente la velocidad y reducir el costo de filtrado de consultas en una columna repetida o no anidada (en nuestro caso, temporada).



La principal desventaja de los campos repetidos anidados es la dificultad de implementar la transmisión en dicha tabla si las actualizaciones de transmisión implican agregar elementos a las matrices existentes. Esto es mucho más difícil de implementar que agregar nuevos registros: deberá modificar un registro existente; para la tabla de información de tormentas, este es un inconveniente significativo, ya que constantemente se agregan nuevas observaciones, y esto explica por qué este conjunto de datos públicos no usa duplicados anidados. campos.



Práctica de usar matrices



La experiencia ha demostrado que se necesita algo de práctica para utilizar con éxito campos repetidos anidados. El conjunto de datos de muestra de Google Analytics en BigQuery es ideal para este propósito. La forma más fácil de identificar datos anidados en un esquema es encontrar la palabra RECORD en la columna Tipo, que corresponde al tipo de datos STRUCT, y la palabra REPEATED en la columna Modo, como se muestra a continuación:





En este ejemplo, el campo TOTALES es STRUCT (pero no se repite) y el campo HITS es STRUCT y se repite. Esto tiene cierto sentido, porque Google Analytics rastrea los datos de la sesión de los visitantes en el nivel de agregación (un valor de sesión para totaless.hits) y en el nivel de granularidad (valores de hit.time separados para cada página e imágenes recuperadas de su sitio) ... El almacenamiento de datos en estos diferentes niveles de detalle sin duplicar el visitanteId en los registros solo es posible con matrices. Después de guardar los datos en un formato repetido con matrices, debe considerar implementar esos datos en sus solicitudes usando UNNEST, por ejemplo:



SELECT DISTINCT
  visitId
  , totals.pageviews
  , totals.timeOnsite
  , trafficSource.source
  , device.browser
  , device.isMobile
  , h.page.pageTitle
FROM
  `bigquery-public-data`.google_analytics_sample.ga_sessions_20170801,
  UNNEST(hits) AS h
WHERE
  totals.timeOnSite IS NOT NULL AND h.page.pageTitle =
'Shopping Cart'
ORDER BY pageviews DESC
LIMIT 10
     ,   [1,2,3,4,5]   :
[1,
2
3
4
5]


A continuación, puede realizar operaciones SQL normales como DÓNDE para filtrar visitas en páginas con títulos como Carrito de la compra. ¡Intentalo!



Por otro lado, el conjunto de datos de información de confirmación pública de GitHub (bigquery-publicdata.githubrepos.commits) usa un campo repetido anidado (reponame) para almacenar la lista de repositorios afectados por la operación de confirmación. No cambia con el tiempo y proporciona consultas más rápidas que se filtran en cualquier otro campo.



Almacenamiento de datos como tipos geográficos



El conjunto de datos públicos de BigQuery incluye una tabla de límites de área de código postal de EE. UU. (Bigquery-public-data.utilityus.zipcodearea) y otra tabla con polígonos que describen los límites de las ciudades de EE. UU. (Bigquery-publicdata.utilityus.uscitiesarea). Una columna zipcodegeom es una cadena, mientras que una columna city_geom es un tipo geográfico.



A partir de estas dos tablas, puede obtener una lista de todos los códigos postales de Santa Fe en Nuevo México, como se muestra a continuación:



SELECT name, zipcode
FROM `bigquery-public-data`.utility_us.zipcode_area
JOIN `bigquery-public-data`.utility_us.us_cities_area
ON ST_INTERSECTS(ST_GeogFromText(zipcode_geom), city_geom)
WHERE name LIKE '%Santa Fe%'


Esta consulta tarda 51,9 segundos, procesa 305,5 MB de datos y devuelve los siguientes resultados:





¿Por qué tarda tanto esta solicitud? No por la operación STINTERSECTS, sino principalmente porque la función STGeogFromText debe evaluar las celdas S2 y construir el tipo GEOGRAPHY correspondiente a cada código postal.



Podemos intentar modificar la tabla de código postal haciendo esto de antemano y almacenar la geometría como un valor de GEOGRAPHY:



CREATE OR REPLACE TABLE ch07.zipcode_area AS
SELECT 
  * REPLACE(ST_GeogFromText(zipcode_geom) AS zipcode_geom)
FROM 
  `bigquery-public-data`.utility_us.zipcode_area


REPLACE (consulte la consulta anterior) es una forma conveniente de reemplazar una columna de una expresión SELECT *.
El nuevo conjunto de datos tiene un tamaño de 131,8 MB, que es significativamente mayor que los 116,5 MB de la tabla original. Sin embargo, las consultas en esta tabla pueden usar la cobertura S2 y son mucho más rápidas. Por ejemplo, la siguiente consulta toma 5.3 segundos (un aumento de 10 veces en la velocidad) y procesa 320.8 MB (un ligero aumento en el costo cuando se utiliza un plan de tarifas "a pedido"):



SELECT name, zipcode
FROM ch07.zipcode_area
JOIN `bigquery-public-data`.utility_us.us_cities_area
ON ST_INTERSECTS(zipcode_geom, city_geom)
WHERE name LIKE '%Santa Fe%'


Los beneficios de rendimiento de almacenar datos geográficos en una columna GEOGRAPHY son más que convincentes. Esta es la razón por la que el conjunto de datos de utilityus está en desuso (todavía está disponible para mantener activas las consultas ya escritas). Recomendamos utilizar la tabla bigquery-public-data.geousbo limits.uszip_codes, que almacena información geográfica en una columna GEOGRAPHY y se actualiza constantemente.



»Más detalles sobre el libro se pueden encontrar en el sitio web de la editorial

» Tabla de contenido

» Extracto



para los habitantes un 25% de descuento en el cupón - Google



Tras el pago de la versión impresa del libro, se envía un libro electrónico al correo electrónico.



All Articles