튜토리얼: Amazon Redshift Spectrum을 사용한 중첩 데이터 쿼리 - Amazon Redshift

튜토리얼: Amazon Redshift Spectrum을 사용한 중첩 데이터 쿼리

개요

Amazon Redshift Spectrum은 Parquet, ORC, JSON 및 Ion 파일 형식에서 중첩 데이터에 대한 쿼리를 지원합니다. Redshift Spectrum은 외부 테이블을 사용하여 데이터에 액세스합니다. 복합 데이터 형식인 struct, arraymap을 사용하는 외부 테이블을 생성할 수 있습니다.

예를 들어 customers라는 폴더에 다음과 같은 Amazon S3 데이터가 저장된 데이터 파일이 있다고 가정하겠습니다. 단일 루트 요소는 없지만 이 샘플 데이터의 각 JSON 객체는 테이블의 행을 나타냅니다.

{"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}] }

Amazon Redshift Spectrum을 사용하여 파일의 중첩된 데이터를 쿼리할 수 있습니다. 다음은 이 방법으로 Apache Parquet 데이터를 쿼리하는 방법을 나타내는 자습서입니다.

자습서 사전 요구 사항, 단계 및 중첩 데이터 사용 사례에 대해서는 다음 주제를 참조하십시오.

사전 조건

Redshift Spectrum을 아직 사용하지 않고 있다면 계속 진행하기 전에 Amazon Redshift Spectrum 시작하기에서 다음 단계를 따르세요.

외부 스키마를 만들려면 다음 명령에서 IAM 역할 ARN을 IAM 역할 생성에서 생성한 역할 ARN으로 대체합니다. 그런 다음 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;

1단계: 중첩 데이터가 포함된 외부 테이블 만들기

Amazon S3에서 소스 데이터를 다운로드하여 볼 수 있습니다.

이번 자습서에서 사용할 외부 테이블을 만들려면 다음과 같이 명령을 실행합니다.

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/';

위의 예에서 외부 테이블 spectrum.customers는 데이터 형식으로 structarray를 사용하여 중첩 데이터가 포함된 열을 정의합니다. Amazon Redshift Spectrum은 Parquet, ORC, JSON 및 Ion 파일 형식에서 중첩 데이터에 대한 쿼리를 지원합니다. STORED AS 파라미터는 Apache Parquet 파일의 경우 PARQUET입니다. LOCATION 파라미터는 중첩 데이터 또는 파일이 들어 있는 Amazon S3 폴더를 참조해야 합니다. 자세한 내용은 CREATE EXTERNAL TABLE 섹션을 참조하세요.

arraystruct 형식은 모든 수준에서 중첩이 가능합니다. 예를 들어 다음 예와 같이 toparray라는 이름으로 열을 정의할 수 있습니다.

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

또한 다음 예의 struct 열처럼 x 형식을 중첩시킬 수도 있습니다.

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

2단계: SQL 확장을 통한 Amazon S3의 중첩 데이터 쿼리

Redshift Spectrum은 Amazon Redshift SQL 구문 확장을 통해 복합 형식인 array, mapstruct에 대한 쿼리를 지원합니다.

확장 1: 구조체 열에 대한 액세스

필드 이름을 경로로 연결하는 점 표기법을 사용해 struct 열에서 데이터를 추출할 수 있습니다. 예를 들어 다음은 고객의 성과 이름을 반환하는 쿼리입니다. 이름은 긴 경로인 c.name.given을 통해 액세스하고, 성은 긴 경로인 c.name.family을 통해 액세스합니다.

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

위의 쿼리는 다음과 같은 데이터를 반환합니다.

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

struct는 어떤 수준에서든지 다른 struct의 열이 될 수 있고, 이 열은 또다시 다른 struct의 열이 될 수 있습니다. 이렇게 깊게 중첩되는 struct의 열에 액세스하는 경로는 계속해서 길어질 수 있습니다. 예를 들어 다음 예에서 x 열에 대한 정의를 보십시오.

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

ex.b.d.e의 데이터에 액세스할 수 있습니다.

확장 2: FROM 절의 포괄적 배열

array 절에서 테이블 이름이 아닌 map 열을 지정하여 array 열(확장 시 FROM 열까지도)의 데이터를 추출할 수 있습니다. 이러한 확장은 기본 쿼리의 FROM 절은 물론이고 하위 쿼리의 FROM 절에도 적용됩니다.

array 요소는 c.orders[0]와 같이 위치로 참조할 수 있습니다(미리 보기).

포괄적 arrays를 조인과 함께 사용하면 다음 사용 사례에서 설명하겠지만 다양한 유형의 중첩 해제가 가능합니다.

내부 조인을 사용한 중첩 해제

다음은 고객 ID와 주문한 고객의 주문 발송일을 선택하는 쿼리입니다. FROM 절의 SQL 확장인 c.orders o는 별칭인 c에 따라 달라집니다.

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

주문한 고객 c마다 FROM 절이 고객 o의 각 주문 c에 대해 행을 하나씩 반환합니다. 각 행은 고객 행 c와 주문 행 o가 함께 표시됩니다. 그러면 SELECT 절에는 c.ido.shipdate만 유지됩니다. 결과는 다음과 같습니다.

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)

별칭 c는 고객 필드에 대한 액세스를, 그리고 별칭 o는 주문 필드에 대한 액세스를 제공합니다.

시맨틱은 표준 SQL과 비슷합니다. FROM 절을 다음 중첩 루프를 실행하는 것으로 생각할 수 있습니다. 이후에는 출력할 필드를 선택하는 SELECT 절이 나옵니다.

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

따라서 주문하지 않은 고객은 결과에서도 표시되지 않습니다.

또한 이것을 FROM 테이블과 JOIN 배열을 사용해 customers을 실행하는 orders 절이라고 생각할 수도 있습니다. 실제로 다음 예와 같이 쿼리를 작성하는 것도 가능합니다.

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

이름이 c인 테이블에 orders라는 스키마가 존재한다면 c.ordersorders의 배열 열이 아닌 customers 테이블을 참조합니다.

왼쪽 조인을 사용한 중첩 해제

다음은 모든 고객 이름과 고객의 주문을 출력하는 쿼리입니다. 따라서 주문하지 않은 고객의 이름까지 모두 반환됩니다. 하지만 이 경우에는 아래 Jenny Doe의 예와 같이 주문 열이 NULL 값을 갖습니다.

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

위의 쿼리는 다음과 같은 데이터를 반환합니다.

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)

확장 3: 별칭을 사용해 스칼라 배열에 직접 액세스

FROM 절의 별칭 p가 스칼라 배열을 포괄하는 경우에는 쿼리가 p 값을 p로 참조합니다. 예를 들어 다음은 고객 이름과 전화 번호를 쌍으로 반환하는 쿼리입니다.

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

위의 쿼리는 다음과 같은 데이터를 반환합니다.

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

확장 4: 맵 요소에 대한 액세스

Redshift Spectrum은 map 데이터 형식을 array 열과 struct 열로 구성된 key 형식이 포함된 value 형식으로 처리합니다. keyscalar가 되어야 하고, 값은 어떤 데이터 형식이든 될 수 있습니다.

예를 들어 다음은 전화 번호를 저장할 목적으로 map이 포함된 외부 테이블을 만드는 코드입니다.

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/';

map 형식은 array 열과 key 열로 구성된 value 형식처럼 처리되기 때문에 앞에 나오는 스키마를 마치 뒤에 나오는 스키마라고 생각할 수 있습니다.

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/';

다음은 고객 이름과 휴대 전화 번호를 함께 반환한 후 각 이름의 번호를 반환하는 쿼리입니다. 맵 쿼리는 array 형식의 중첩 struct를 쿼리하는 것과 동일하게 처리됩니다. 다음은 앞에서 설명한 외부 테이블을 만든 경우에만 데이터를 반환하는 쿼리입니다.

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

key에 대한 map는 Ion 및 JSON 파일 형식에 대한 string입니다.