Tutorial: Consulta de datos anidados con Amazon Redshift Spectrum - Amazon Redshift

Tutorial: Consulta de datos anidados con Amazon Redshift Spectrum

En este tutorial se muestra cómo consultar datos anidados con Redshift Spectrum. Los datos anidados son datos que contienen campos anidados. Los campos anidados son campos que se unen como una sola entidad, por ejemplo, matrices, estructuras u objetos.

Información general

Amazon Redshift Spectrum admite la consulta de datos anidados en los formatos de archivos Parquet, ORC, JSON e Ion. Redshift Spectrum obtiene acceso a los datos mediante el uso de tablas externas. Puede crear tablas externas que usen los tipos de datos complejos struct, array y map.

Supongamos, por ejemplo, que su archivo de datos contiene los siguientes datos en Amazon S3 en una carpeta llamada customers. Aunque no hay un solo elemento raíz, cada objeto JSON de estos datos de ejemplo representa una fila en una tabla.

{"id": 1, "name": {"given": "John", "family": "Smith"}, "phones": ["123-457789"], "orders": [{"shipdate": "2018-03-01T11:59:59.000Z", "price": 100.50}, {"shipdate": "2018-03-01T09:10:00.000Z", "price": 99.12}] } {"id": 2, "name": {"given": "Jenny", "family": "Doe"}, "phones": ["858-8675309", "415-9876543"], "orders": [] } {"id": 3, "name": {"given": "Andy", "family": "Jones"}, "phones": [], "orders": [{"shipdate": "2018-03-02T08:02:15.000Z", "price": 13.50}] }

Puede usar Amazon Redshift Spectrum para consultar datos anidados en archivos. El siguiente tutorial le muestra cómo hacerlo con los datos de Apache Parquet.

Requisitos previos

Si aún no usa Redshift Spectrum, siga los pasos en el tutorial de Introducción a Amazon Redshift Spectrum antes de continuar.

Para crear un esquema externo, reemplace el ARN del rol de IAM en el siguiente comando por el ARN del rol que creó en Creación de un rol de IAM. Luego, ejecute el comando en cliente SQL.

create external schema spectrum from data catalog database 'myspectrum_db' iam_role 'arn:aws:iam::123456789012:role/myspectrum_role' create external database if not exists;

Paso 1: Crear una tabla externa que contenga datos anidados

Puede ver el origen de datos descargándolo de Amazon S3.

Para crear la tabla externa para este tutorial, ejecute el siguiente comando.

CREATE EXTERNAL TABLE spectrum.customers ( id int, name struct<given:varchar(20), family:varchar(20)>, phones array<varchar(20)>, orders array<struct<shipdate:timestamp, price:double precision>> ) STORED AS PARQUET LOCATION 's3://redshift-downloads/tickit/spectrum/customers/';

En el ejemplo anterior, la tabla externa spectrum.customers utiliza los tipos de datos struct y array para definir columnas con datos anidados. Amazon Redshift Spectrum admite la consulta de datos anidados en los formatos de archivos Parquet, ORC, JSON e Ion. El parámetro STORED AS es PARQUET para los archivos de Apache Parquet. El parámetro LOCATION tiene que hacer referencia a la carpeta de Amazon S3 que contiene los datos o los archivos anidados. Para obtener más información, consulte CREATE EXTERNAL TABLE.

Puede anidar tipos array y struct en cualquier nivel. Por ejemplo, puede definir una columna denominada toparray tal como se muestra en el siguiente ejemplo.

toparray array<struct<nestedarray: array<struct<morenestedarray: array<string>>>>>

También puede anidar los tipos struct tal como se muestra para la columna x en el siguiente ejemplo.

x struct<a: string, b: struct<c: integer, d: struct<e: string> > >

Paso 2: Consultar los datos anidados en Amazon S3 con extensiones SQL

Redshift Spectrum permite consultar los tipos complejos array, map y struct mediante extensiones de la sintaxis SQL de Amazon Redshift.

Extensión 1: Acceso a columnas de estructuras

Puede extraer datos de columnas de struct mediante una notación de puntos que concatene nombres de campos para crear rutas. Por ejemplo, la siguiente consulta devuelve los nombres y los apellidos de los clientes. El acceso al nombre se consigue con la ruta larga c.name.given. El acceso al apellido se consigue con la ruta larga c.name.family.

SELECT c.id, c.name.given, c.name.family FROM spectrum.customers c;

La consulta anterior devuelve los siguientes datos.

id | given | family ---|-------|------- 1 | John | Smith 2 | Jenny | Doe 3 | Andy | Jones (3 rows)

Una struct puede ser una columna de otra struct, que a su vez puede ser una columna de otra struct, en cualquier nivel. Las rutas que ofrecen acceso a columnas en struct profundamente anidadas pueden ser arbitrariamente largas. Por ejemplo, consulte la definición de la columna x a continuación.

x struct<a: string, b: struct<c: integer, d: struct<e: string> > >

Puede obtener acceso a los datos en e como x.b.d.e.

Extensión 2: Desplazamiento por matrices en una cláusula FROM

Puede extraer datos de columnas array (y, por extensión, de columnas map) especificando las columnas array en una cláusula FROM en lugar de nombres de tablas. La extensión se aplica a la cláusula FROM de la consulta principal y también a las cláusulas FROM de las subconsultas.

Puede hacer referencia a los elementos array por posición como, por ejemplo, c.orders[0]. (versión preliminar)

Mediante la combinación del desplazamiento por arrays con las uniones, se pueden conseguir varios tipos de aplanamientos, tal como se explica en los siguientes casos de uso.

Aplanamiento mediante combinaciones interiores

La siguiente consulta selecciona los ID de cliente y las fechas de envío de los pedidos para los clientes que tienen pedidos. La extensión SQL en la cláusula FROM c.orders o depende del alias c.

SELECT c.id, o.shipdate FROM spectrum.customers c, c.orders o

Para cada cliente c que tiene pedidos, la cláusula FROM devuelve una fila para cada pedido o del cliente c. La fila combina la fila de cliente c y la fila de pedido o. A continuación, la cláusula SELECT solo conserva c.id y o.shipdate. El resultado es el siguiente.

id| shipdate --|---------------------- 1 |2018-03-01 11:59:59 1 |2018-03-01 09:10:00 3 |2018-03-02 08:02:15 (3 rows)

El alias c proporciona acceso a los campos del cliente y el alias o proporciona acceso a los campos de los pedidos.

Las semánticas son similares al SQL estándar. Puede considerar una cláusula FROM como si ejecutara el siguiente bucle anidado, seguido de SELECT para elegir los campos de la salida.

for each customer c in spectrum.customers for each order o in c.orders output c.id and o.shipdate

Por consiguiente, si un cliente no tuviera un pedido, no aparecería en el resultado.

También puede considerar esto como la cláusula FROM que realiza una JOIN con la tabla customers y la matriz orders. De hecho, también puede escribir la consulta tal como se muestra en el siguiente ejemplo.

SELECT c.id, o.shipdate FROM spectrum.customers c INNER JOIN c.orders o ON true
nota

Si existe un esquema denominado c con una tabla llamada orders, entonces c.orders hará referencia a la tabla orders y no a la columna matriz de customers.

Aplanamiento mediante combinaciones izquierdas

La siguiente consulta devuelve todos los nombres de los clientes y sus pedidos. Si un cliente no ha realizado ningún pedido, también se devolverá el nombre del cliente. No obstante, en este caso, las columnas de pedido son NULL, tal y como se muestra en el siguiente ejemplo para Jenny Doe.

SELECT c.id, c.name.given, c.name.family, o.shipdate, o.price FROM spectrum.customers c LEFT JOIN c.orders o ON true

La consulta anterior devuelve los siguientes datos.

id | given | family | shipdate | price ----|---------|---------|----------------------|-------- 1 | John | Smith | 2018-03-01 11:59:59 | 100.5 1 | John | Smith | 2018-03-01 09:10:00 | 99.12 2 | Jenny | Doe | | 3 | Andy | Jones | 2018-03-02 08:02:15 | 13.5 (4 rows)

Extensión 3: Acceso a una matriz de escalares directamente mediante un alias

Cuando un alias p en una cláusula FROM toma valores de una matriz de escalares, la consulta hace referencia a los valores de p como p. Por ejemplo, la siguiente consulta devuelve pares de nombres de clientes y números de teléfono.

SELECT c.name.given, c.name.family, p AS phone FROM spectrum.customers c LEFT JOIN c.phones p ON true

La consulta anterior devuelve los siguientes datos.

given | family | phone -------|----------|----------- John | Smith | 123-4577891 Jenny | Doe | 858-8675309 Jenny | Doe | 415-9876543 Andy | Jones | (4 rows)

Extensión 4: Acceso a elementos de asignaciones

Redshift Spectrum trata el tipo de dato map como un tipo array que contiene tipos struct con una columna key y una columna value. La columna key debe ser scalar; el valor puede ser cualquier tipo de dato.

Por ejemplo, el siguiente código crea una tabla externa con map para almacenar números de teléfono.

CREATE EXTERNAL TABLE spectrum.customers2 ( id int, name struct<given:varchar(20), family:varchar(20)>, phones map<varchar(20), varchar(20)>, orders array<struct<shipdate:timestamp, price:double precision>> ) STORED AS PARQUET LOCATION 's3://redshift-downloads/tickit/spectrum/customers/';

Como un tipo map se comporta igual que un tipo array con columnas key y value, puede considerar los anteriores esquemas como si fueran el siguiente.

CREATE EXTERNAL TABLE spectrum.customers3 ( id int, name struct<given:varchar(20), family:varchar(20)>, phones array<struct<key:varchar(20), value:varchar(20)>>, orders array<struct<shipdate:timestamp, price:double precision>> ) STORED AS PARQUET LOCATION 's3://redshift-downloads/tickit/spectrum/customers/';

La siguiente consulta devuelve los nombres de clientes con un número de teléfono móvil, y devuelve el número para cada nombre. La consulta de asignaciones se trata como si fuera el equivalente a consultar una array anidada de tipos struct. La siguiente consulta solo devolverá datos si creó la tabla externa tal y como se describió anteriormente.

SELECT c.name.given, c.name.family, p.value FROM spectrum.customers c, c.phones p WHERE p.key = 'mobile';
nota

La columna key para una map es una string para los tipos de archivo de Ion y JSON.