Tutorial: Consultar dados aninhados com o Amazon Redshift Spectrum
Este tutorial demonstra como consultar dados aninhados com o Redshift Spectrum. Dados aninhados são dados que contêm campos aninhados. Campos aninhados são campos unidos como uma única entidade (por exemple, matrizes, structs ou objetos).
Tópicos
Visão geral
O Amazon Redshift Spectrum oferece suporte a consulta de dados aninhados em formatos de arquivo Parquet, ORC, JSON e Ion. O Redshift Spectrum acessa dados usando tabelas externas. Você pode criar tabelas externas usando os tipos de dados complexos struct
, array
e map
.
Por exemplo, suponha que o arquivo de dados contém os seguintes dados no Amazon S3 em uma pasta nomeada customers
. Embora não haja um elemento raiz único, cada objeto JSON nestes dados de exemplo representa uma linha em uma tabela.
{"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}]
}
Você pode usar o Amazon Redshift Spectrum para consultar dados aninhados em arquivos. O tutorial a seguir mostra como fazer isso com dados do Apache Parquet.
Pré-requisitos
Se você ainda não estiver usando o Redshift Spectrum, acompanhe as etapas no Conceitos básicos do Amazon Redshift Spectrum antes de continuar.
Para criar um esquema externo, substitua o ARN do perfil do IAM no comando a seguir pelo ARN do perfil que você criou em Criar um perfil do IAM. Execute o comando no 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;
Etapa 1: Crie uma tabela externa que contém dados aninhados
Você pode visualizar a fonte de dados
Para criar a tabela externa para este tutorial, execute o seguinte 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/';
No exemplo que precede, a tabela externa spectrum.customers
usa os tipos de dados struct
e array
para definir colunas com dados aninhados. O Amazon Redshift Spectrum oferece suporte a consulta de dados aninhados em formatos de arquivo Parquet, ORC, JSON e Ion. O parâmetro STORED AS
é PARQUET
para arquivos do Apache Parquet. O parâmetro LOCATION
deve se referir à pasta do Amazon S3 que contém os dados ou arquivos aninhados. Para ter mais informações, consulte CREATE EXTERNAL TABLE.
Você pode aninhar os tipos array
e struct
em qualquer nível. Por exemplo, você pode definir uma coluna nomeada toparray
conforme exibido no seguinte exemplo.
toparray array<struct<nestedarray: array<struct<morenestedarray: array<string>>>>>
Você também pode aninhar os tipos struct
como exibido na coluna x
no exemplo a seguir.
x struct<a: string,
b: struct<c: integer,
d: struct<e: string>
>
>
Etapa 2: Consultar os dados aninhados no Amazon S3 com extensões SQL
O Redshift Spectrum oferece suporte a tipos complexos de array
, map
e struct
por meio das extensões de sintaxe SQL do Amazon Redshift SQL.
Extensão 1: Acesso a colunas de estruturas
Você pode extrair dados das colunas struct
usando uma notação de ponto que concatene nomes de campo em caminhos. Por exemplo, a consulta a seguir retorna nomes e nomes de família de clientes. O nome é acessado pelo caminho longo c.name.given
. O nome de família é acessado pelo caminho longo c.name.family
.
SELECT c.id, c.name.given, c.name.family
FROM spectrum.customers c;
A consulta anterior retorna os dados a seguir.
id | given | family
---|-------|-------
1 | John | Smith
2 | Jenny | Doe
3 | Andy | Jones
(3 rows)
Uma struct
pode ser uma coluna de outro struct
, que pode ser uma coluna de outro struct
, em qualquer nível. Os caminhos que acessa as colunas em struct
aninhados de forma profunda podem ser arbitrariamente longos. Por exemplo, consulte a definição da coluna x
no seguinte exemplo.
x struct<a: string,
b: struct<c: integer,
d: struct<e: string>
>
>
Você pode acessar os dados em e
como x.b.d.e
.
Extensão 2: Variação sobre matriz em uma cláusula FROM
Você pode extrair dados das colunas array
(e, por extensão, colunas map
) especificando as colunas array
em uma cláusula FROM
no lugar de nomes de tabela. A extensão aplica-se à cláusula FROM
da consulta principal, e também as cláusulas FROM
das subconsultas.
Você pode referenciar elementos array
por posição, como c.orders[0]
. (visualização)
Ao combinar a variação do arrays
com junções, você pode alcançar vários tipos de não-aninhamento, como explicado os seguintes casos de uso.
Não aninhamento usando junções internas
A consulta a seguir selecione IDs de cliente e datas de envio de pedido de clientes que têm pedidos. A extensão do SQL na cláusula FROM c.orders
o
depende do alias c
.
SELECT c.id, o.shipdate
FROM spectrum.customers c, c.orders o
Para cada cliente c
que possui pedidos, a cláusula FROM
retorna uma linha para cada pedido o
do cliente c
. Essa linha combina a linha do cliente c
e a linha de pedidos o
. Em seguida, a cláusula SELECT
mantém somente c.id
e o.shipdate
. O resultado é o seguinte.
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)
O alias c
fornece acesso aos campos de clientes, e o alias o
fornece acesso aos campos de pedidos.
A semântica é semelhante ao SQL padrão. Você pode pensar na cláusula FROM
como executando o loop aninhado a seguir, que é acompanhado por SELECT
escolhendo os campos para saída.
for each customer c in spectrum.customers
for each order o in c.orders
output c.id and o.shipdate
Portanto, se um cliente não tiver um pedido, o cliente não aparece no resultado.
Você também pode considerá-lo como cláusula FROM
da execução JOIN
com a tabela customers
e o array orders
. Na verdade, você também pode escrever a consulta, conforme mostrado no exemplo a seguir.
SELECT c.id, o.shipdate
FROM spectrum.customers c INNER JOIN c.orders o ON true
nota
Se um esquema nomeado c
existe com uma tabela nomeada orders
, então c.orders
refere-se a tabela orders
, e não a coluna de matriz de customers
.
Não aninhamento usando junções à esquerda
A consulta a seguir exibe todos os nomes de clientes e seus pedidos. Se um cliente não fez um pedido, o nome do cliente ainda é retornado. Contudo, nesse caso, as colunas de pedido são NULL, conforme mostrado no exemplo a seguir 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
A consulta anterior retorna os dados a seguir.
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)
Extensão 3: Acessar uma matriz de escalares usando diretamente um alias
Quando um alias p
em intervalos de uma cláusula FROM
percorre uma matriz de escalares, a consulta se refere aos valores de p
como p
. Por exemplo, a consulta a seguir produz pares de nomes de clientes e de números de telefone.
SELECT c.name.given, c.name.family, p AS phone
FROM spectrum.customers c LEFT JOIN c.phones p ON true
A consulta anterior retorna os dados a seguir.
given | family | phone
-------|----------|-----------
John | Smith | 123-4577891
Jenny | Doe | 858-8675309
Jenny | Doe | 415-9876543
Andy | Jones |
(4 rows)
Extensão 4: Acessar elementos de mapas
Redshift Spectrum trata o tipo de dados map
como um tipo array
que contém tipos struct
com uma coluna key
e uma coluna value
. O key
deve ser um scalar
; o valor pode ser qualquer tipo de dados.
Por exemplo, o seguinte código criar uma tabela externa com um map
para armazenar números de telefone.
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 um tipo map
se comporta como um tipo array
com colunas key
e value
, você pode entender os esquemas anteriores como os seguintes.
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/';
A consulta a seguir retorna os nomes de clientes com um número de celular e retorna a quantidade para cada nome. A consulta de mapeamento é tratada como o equivalente de consulta dos tipos array
de struct
aninhados. A consulta a seguir retorna somente dados se você tiver criado a tabela externa como descrito previamente.
SELECT c.name.given, c.name.family, p.value
FROM spectrum.customers c, c.phones p
WHERE p.key = 'mobile';
nota
O key
de um map
é um string
para tipos de arquivo Ion e JSON.