Descripción general
La arquitectura de procesamiento de Earth Engine está optimizada para que el procesamiento de imágenes (basado en píxeles) sea rápido y escalable. BigQuery también está optimizado para el procesamiento escalable de datos tabulares (vectores) y tiene muchas funciones que lo convierten en un buen complemento de Earth Engine.
Estos son algunos ejemplos de flujos de trabajo:
- Cómo realizar grandes combinaciones de BigQuery en datos generados en Earth Engine
- Anotación de datos vectoriales con estadísticas derivadas de imágenes para un procesamiento adicional en BigQuery
- Exporta datos de Earth Engine de forma periódica a una tabla de BigQuery que se pueda agregar
Si tienes otros casos de uso interesantes, nos encantaría conocerlos.
Conceptos básicos de BigQuery
Earth Engine escribe en tablas de BigQuery, y todas las tablas se contienen en conjuntos de datos. Las tareas de exportación fallan si el conjunto de datos especificado no está presente en BigQuery. Obtén más información en la introducción al conjunto de datos de BigQuery.
Creación de conjuntos de datos
Los conjuntos de datos tienen varias opciones de tiempo de creación, como el nombre, la región de almacenamiento y el comportamiento de vencimiento (junto con varias otras opciones más avanzadas).
Existen varios mecanismos para crear conjuntos de datos, pero una manera simple de comenzar es a través de la consola de Cloud:
- Navega a la página de BigQuery en la consola de Cloud.
- Haz clic en “Habilitar” para habilitar la API, si se te solicita.
- En la pestaña "Espacio de trabajo de SQL", haz clic en el menú de tres puntos ( ) junto al proyecto.
- Elige la opción “Crear conjunto de datos”.
- Sigue la guía de configuración.
Para ver todas las opciones para crear y configurar un conjunto de datos, consulta la documentación de BigQuery.
Permisos
Además de los roles y permisos estándar necesarios para usar Earth Engine, los llamadores también necesitan los permisos de BigQuery correctos en el proyecto o el conjunto de datos de Cloud.
bigquery.tables.get
bigquery.tables.create
bigquery.tables.updateData
bigquery.tables.delete
bigquery.jobs.create
Cualquiera de las siguientes combinaciones de roles predefinidos de Identity and Access Management (IAM) incluye los permisos necesarios:
bigquery.dataEditor
másbigquery.jobUser
bigquery.dataOwner
másbigquery.jobUser
bigquery.user
bigquery.admin
Precios
BigQuery es un servicio pagado de Google Cloud, por lo que se generarán cargos por el uso de BigQuery, incluido el almacenamiento y el análisis de los datos de Earth Engine que exportes a BigQuery.
Para obtener detalles sobre los precios de la función de exportación a BigQuery de Earth Engine, consulta la sección de precios a continuación.
Exportar configuración
Sintaxis
Export.table.toBigQuery({
'collection': myFeatureCollection,
'table': 'myproject.mydataset.mytable',
'description': 'put_my_data_in_bigquery',
'append': true,
'overwrite': false
});
task = ee.batch.Export.table.toBigQuery(
collection=myFeatureCollection,
table='myproject.mydataset.mytable',
description='put_my_data_in_bigquery',
append=True,
overwrite=False)
task.start()
Especificación del esquema automática o manual
Si no hay ninguna tabla en BigQuery, Earth Engine intenta determinar un esquema con las propiedades del primer ee.Feature
de la colección. Esta es una suposición razonable, y es posible construir una colección en la que el esquema de la primera función sea diferente del esquema de otras funciones.
Si necesitas un esquema específico en tu tabla de BigQuery, configúralo creando una tabla vacía con el esquema de destino.
Nombres de las propiedades
Las propiedades de los atributos de Earth Engine corresponden a columnas de BigQuery. Earth Engine usa el nombre "geo" para escribir la geometría ee.Feature
(el selector ".geo") en BigQuery.
Para evitar que se cambie el nombre, asegúrate de que tus objetos ee.Feature
tengan propiedades que sean nombres de columna válidos y que ninguno se llame "geo" (ya que este nombre se usa para la geometría del componente, que no tiene nombre en Earth Engine).
Los caracteres no válidos en los nombres de las propiedades hacen que la exportación falle debido a las restricciones en los nombres de las columnas de BigQuery.
Conversión de tipos
Los datos de Earth Engine (los valores de las propiedades ee.Feature
) se convierten en un tipo de BigQuery equivalente cuando es posible. Ten en cuenta que el esquema de la tabla controla la nulabilidad, no el tipo.
Tipo de Earth Engine | Tipo de BigQuery | Notas |
---|---|---|
ee.String |
STRING |
|
ee.Number
|
FLOAT o bien INTEGER
|
|
ee.Geometry |
GEOGRAPHY |
|
ee.Date |
TIMESTAMP |
|
ee.ByteString |
BYTES |
|
ee.Array
|
STRUCT<ARRAY<INT64>,
ARRAY<INT64|FLOAT64>> |
Consulta la sección sobre arrays. |
Otros tipos de ee.*
|
not supported | Consulta la sección sobre valores JSON. |
Arrays
Earth Engine exporta cualquier ee.Array
multidimesional a STRUCT<ARRAY<INT64> dimensions, ARRAY<INT64|FLOAT64> values>
, similar al formato que usa la función ML.DECODE_IMAGE de BigQuery.
El primer array de la estructura, dimensions
, contiene las dimensiones del array de Earth Engine, de d1 a dn.
El segundo array en la struct, values
, contiene todos los valores del array multidimensiona, aplanados en un solo array de BigQuery.
La cantidad total de valores en el array aplanado es ∑ni=1di, y el valor en el índice (ii,…,in) en el array original de Earth Engine corresponde al valor en el siguiente índice en el array aplanado:
n∑j=1(ij⋅n∏k=j+1dk)
En los casos comunes, la expresión de indexación para el array values
es la siguiente:
Tamaño del array | Dimensiones | Expresión de indexación |
---|---|---|
1 dimensión | d1 |
[i1] |
2 dimensiones | d1, d2 |
[(i1 * d2) + i2] |
Tridimensional | d1, d2, d3 |
[(i1 * d2 * d3) + (i2 * d3) + i3] |
Por ejemplo, considera un array de Earth Engine 2x3x4
:
ee.Array([
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
],
[
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]
]
]);
Este array se traduce a un STRUCT
de BigQuery cuyo elemento dimensions
es el array [2, 3, 4]
y cuyo elemento values
es el array aplanado [1, 2, 3, 4, 5, 6, 7, 8, ..., 21, 22, 23, 24]
.
Los índices del array aplanado se pueden calcular como [(i1 * 12) + (i2 * 4) + i3]
.
Valores JSON
Para admitir datos más estructurados dentro de una celda, es posible codificar los valores de Earth Engine como objetos JSON. BigQuery admite operaciones de SQL en datos codificados en JSON, lo que permite realizar consultas que “busquen dentro” de los valores JSON codificados que generas en Earth Engine.
var states = ee.FeatureCollection('TIGER/2018/States'); var mod11a1 = ee.ImageCollection('MODIS/061/MOD11A1'); // Find the max day and night temperatures per pixel for a given time. var maxTemp = mod11a1 .select(['LST_Day_1km', 'LST_Night_1km']) .filterDate('2023-05-15', '2023-05-25') .max(); // Annotate each state with its max day/night temperatures. var annotatedStates = states.map(function (e) { var dict = maxTemp.reduceRegion({ reducer: ee.Reducer.max(), geometry: e.geometry(), scale: 10 * 1000, // 10 km }); // Convert the dictionary to JSON and add it as a property. return e.set('maxTemp', ee.String.encodeJSON(dict)); }); Export.table.toBigQuery(annotatedStates);
import ee import geemap.core as geemap
states = ee.FeatureCollection('TIGER/2018/States') mod11a1 = ee.ImageCollection('MODIS/061/MOD11A1') # Find the max day and night temperatures per pixel for a given time. max_temp = ( mod11a1.select(['LST_Day_1km', 'LST_Night_1km']) .filterDate('2023-05-15', '2023-05-25') .max() ) def get_max_temp_for_state(e): max_temp_dict = max_temp.reduceRegion( reducer=ee.Reducer.max(), geometry=e.geometry(), scale=10 * 1000, # 10 km ) # Convert the dictionary to JSON and add it as a property. return e.set('maxTemp', ee.String.encodeJSON(max_temp_dict)) # Annotate each state with its max day/night temperatures. annotated_states = states.map(get_max_temp_for_state) task = ee.batch.Export.table.toBigQuery( collection=annotated_states, table='myproject.mydataset.mytable' ) task.start()
Conversión de geometría
BigQuery tiene compatibilidad limitada con diferentes proyecciones, por lo que todas las geometrías de Earth Engine se transforman en EPSG:4326
geodésico con un margen de error de 1 metro.
Para tener un control más preciso sobre este proceso de transformación, puedes asignar manualmente los componentes y transformar sus geometrías, p.ej.:
var transformedCollection = originalCollection.map(function transformGeo(e) { var myErrorMargin = 10 * 1000; // meters return e.setGeometry(e.geometry(myErrorMargin, 'EPSG:4326', true)); });
import ee import geemap.core as geemap
def transform_geo(e): my_error_margin = 10 * 1000 # meters return e.setGeometry(e.geometry(my_error_margin, 'EPSG:4326', True)) transformed_collection = original_collection.map(transform_geo)
Rendimiento
Rendimiento de Earth Engine
El procesamiento de Earth Engine suele ser el cuello de botella de las operaciones de Export
. Para
ello, es importante organizar el procesamiento para obtener el máximo paralelismo.
Cualquier cálculo que se compile en el procesamiento en serie (por ejemplo, ee.FeatureCollection.iterate()
) puede hacer que la exportación se ejecute con lentitud o falle.
Rendimiento en BigQuery
La mejor manera de garantizar que las consultas se puedan realizar de manera eficiente en BigQuery es estructurar y agrupar los datos correctamente. Si no hay una tabla presente en BigQuery, las tablas exportadas de Earth Engine se agrupan en la geometría de los componentes (si está presente). El agrupamiento por el campo de ubicación geográfica es muy común para los datos geoespaciales. Mejora el rendimiento y reduce el costo de las consultas que usan filtros espaciales, lo que suele ocurrir en operaciones de BigQuery como las siguientes:
WHERE ST_DWithin(<table_column>, <constant_geography>, <distance>)
WHERE ST_Intersects(<table_column>, <constant_geography>)
Por lo general, agregar el agrupamiento a una tabla no agrupada tampoco perjudica nada, aunque podría aumentar ligeramente el tiempo de carga de datos en la tabla. Para obtener más información sobre la optimización de consultas, consulta la documentación de BigQuery.
Ten en cuenta que la configuración de agrupamiento solo afecta a los datos nuevos que se escriben en la tabla.
Demostración: Cómo usar reduceRegions
En algunos casos, es posible usar reduceRegions
para obtener el mayor paralelismo posible de la infraestructura de procesamiento de Earth Engine. En este ejemplo, se muestra cómo usar una menor cantidad de llamadas a reduceRegions
(cientos) en lugar de decenas de miles de llamadas a reduceRegion
(el enfoque típico para asignar una función a una colección).
var lucas = ee.FeatureCollection('JRC/LUCAS_HARMO/COPERNICUS_POLYGONS/V1/2018'); var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED'); // Fetch the unique date values from the dataset. var dates = lucas.aggregate_array('survey_date') .distinct() .map(function (date) { return ee.Date.parse('dd/MM/yy', date); }); // For each date, annotate the LUCAS samples with the Sentinel-2 band values for // a two-week window. function getLucasSamplesForDate(date) { date = ee.Date(date); var imageForDate = s2 .filterDate( date.advance(-1, 'week'), date.advance(1, 'week')) .select('B.*'); var median = imageForDate.median(); var lucasForDate = lucas.filter( ee.Filter.equals('survey_date', date.format('dd/MM/yy'))); var sample = median.reduceRegions({ collection: lucasForDate, reducer: ee.Reducer.mean(), scale: 10, tileScale: 8, }); return sample; } // Flatten the collection. var withSamples = ee.FeatureCollection(dates.map(getLucasSamplesForDate)) .flatten(); Export.table.toBigQuery({ collection: withSamples, description: 'lucas_s2_annotated' });
import ee import geemap.core as geemap
lucas = ee.FeatureCollection('JRC/LUCAS_HARMO/COPERNICUS_POLYGONS/V1/2018') s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') # Fetch the unique date values from the dataset. dates = ( lucas.aggregate_array('survey_date') .distinct() .map(lambda date: ee.Date.parse('dd/MM/yy', date)) ) # For each date, annotate the LUCAS samples with the Sentinel-2 band values for # a two-week window. def get_lucas_samples_for_date(date): date = ee.Date(date) image_for_date = s2.filterDate( date.advance(-1, 'week'), date.advance(1, 'week') ).select('B.*') median = image_for_date.median() lucas_for_date = lucas.filter( ee.Filter.equals('survey_date', date.format('dd/MM/yy')) ) sample = median.reduceRegions( collection=lucas_for_date, reducer=ee.Reducer.mean(), scale=10, tileScale=8, ) return sample # Flatten the collection. with_samples = ee.FeatureCollection( dates.map(get_lucas_samples_for_date) ).flatten() task = ee.batch.Export.table.toBigQuery( collection=with_samples, table='myproject.mydataset.mytable', description='lucas_s2_annotated', ) task.start()
Paralelización de tareas
Con la opción {append: true}
, es posible que varias tareas escriban datos
en una tabla de BigQuery de forma simultánea. Este es un mecanismo para escribir datos con una mayor productividad, pero a costa de una mayor complejidad (administrar la cola de tareas, reintentarlo, etcétera).
Diferencias de rendimiento entre los parámetros append
y overwrite
Ten en cuenta que la anulación es más lenta que la adición, ya que BigQuery debe procesar los datos nuevos antes de anular los anteriores. Si configuras el parámetro {overwrite: true} cuando exportas a una tabla de BigQuery existente, se activa un proceso de reemplazo seguro:
- Tabla temporal: Los datos se exportan a una tabla nueva y temporal dentro del conjunto de datos de destino.
- Reemplazo atómico: El contenido de la tabla temporal se copia en la tabla de destino final y reemplaza los datos existentes en una sola transacción atómica.
- Limpieza: Se borra la tabla temporal.
Esto garantiza que los errores durante la exportación no dañen tus datos existentes. En el caso de las tablas pequeñas, la demora suele ser de unos minutos.
Alternativas de alto rendimiento
Para los flujos de trabajo que requieren una capacidad de procesamiento muy alta, considera usar GeoBeam para mover datos de Earth Engine a BigQuery. Esto requiere más configuración e infraestructura, por lo que te sugerimos que comiences con la funcionalidad integrada de Earth Engine.
Precios
La exportación a BigQuery es un proceso por lotes que consume tiempo de EECU por lotes. Si usas Earth Engine de forma comercial o operativa, la exportación de datos a BigQuery te cobra el tiempo de EECU que usan las tareas. Todo el uso se puede supervisar con las mismas herramientas de supervisión que funcionan para el resto de Earth Engine.
Cuentas de facturación de Cloud
Para escribir datos en BigQuery, el proyecto de Cloud asociado debe tener habilitada una cuenta de facturación. Para obtener más información sobre la configuración de la cuenta de facturación, consulta la documentación de la cuenta de facturación de Cloud.
Salida
Todos los costos de entrada y salida se cobran como tráfico de red estándar.
Earth Engine solo se aloja en EE.UU., pero los conjuntos de datos de BigQuery se pueden alojar en varias otras regiones. Según las regiones y los volúmenes de datos involucrados, escribir datos de Earth Engine a BigQuery puede generar un tráfico de red considerable.
Problemas conocidos
Orientación para polígonos grandes
La función de exportación de BigQuery invierte los polígonos que son más grandes que un hemisferio revirtiendo su orientación (cambiando el polígono a su complemento geométrico). En casos excepcionales, es posible que no se carguen los polígonos más grandes que un hemisferio.
Si es necesario, los polígonos invertidos se pueden corregir en BigQuery. Para ello, vuelve a invertirlos con la expresión ST_Difference(ST_GeogFromText('fullglobe'), geo)
de BigQuery.
Para obtener más información, consulta este artículo.