Amazon Web Services ブログ
Amazon Redshift Spectrum を使用してネストされたデータ型を扱う
Redshift Spectrum は Amazon Redshift の機能で、Amazon S3 に保存されたデータを直接クエリでき、ネストされたデータ型をサポートします。この記事では、ネストされたデータ型からメリットが得られるユースケース、ネストされたデータ型で Amazon Redshift Spectrum を使用して優れたパフォーマンスとストレージ効率を達成する方法、およびネストされたデータ型のいくつかの制約について説明します。
この記事では、ダミーデータで生成されたデータセットを使用します。テーブルスキーマを表示できます。データセットを試したい場合、Redshift クラスターをデプロイし、そこで DDL を実行して、この記事のクエリ例を使用するか、独自のクエリを作成します。
データモデリング
多くのシナリオでは、データは階層で生成されます。たとえば、顧客がいくつかのアイテムを購入したとします。分析のために、ストレージを節約したりデータ処理を高速化したりするためのさまざまなデータモデリングアプローチがあります。ストレージ効率を達成するための一般的なアプローチの 1 つは、次元モデルです。
次のテーブルに、ダミーの顧客データを示します。
username | name | sex | address | birthdate | ||
1 | erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 |
2 | shepherdlisa | Mark Lee | M | 754 Michelle Gateway Port Johnstad, ME 35695 | guerrerotodd@hotmail.com | 1932/11/10 |
3 | palmerpaul | Jennifer Marshall | F | 869 Harrell Forges Apt.111 East Monica, MO 01243 | heather65@hotmail.com | 2007/3/11 |
4 | brettmcgee | Travis Wilson | M | 535 Lisa Flat East Andrew, ID 43332 | bellkim@gmail.com | 2010/3/22 |
5 | torresdiana | Ashley Hoffman | F | 7815 Lauren Ranch Ambertown, FL 93225 | franklinjonathan@hotmail.com | 1960/5/14 |
次のテーブルにはダミーの注文データが含まれており、外部キーのユーザー名を介して顧客テーブルにリンクされています。
username | transaction_date | shipping_date | items | price | |
1 | erin15 | 2019/10/11 | 2019/10/13 | 10 | 4794 |
2 | erin15 | 2019/10/11 | 2019/10/12 | 7 | 1697 |
3 | erin15 | 2019/10/7 | 2019/10/9 | 2 | 15 |
4 | erin15 | 2019/10/6 | 2019/10/10 | 5 | 1744 |
5 | erin15 | 2019/10/5 | 2019/10/10 | 7 | 6346 |
次元モデルでは、各顧客の情報は 1 回だけ保存されます。顧客がさまざまな時間に複数のアイテムを注文できたとしても、重複したデータはありません。
次元モデルはストレージに最適です。ただし、データを効率的に処理することは困難になり得ます。データの全体像を把握するには、2 つのテーブルを結合して階層を復元する必要があります。
たとえば、顧客が Mark Lee が過去 3 か月に購入したアイテムの数と合計支出を調べるには、クエリは顧客と注文のテーブルを結合する必要があります。次のコードを参照してください。
各トランザクションで複数のアイテムを購入する可能性のある何百万もの顧客がいる場合、結合は非常にコストがかかる可能性があります。急成長するデータセットは非常に大きくなる可能性があるため、分散システムに保存する必要があります。結合を実行するには、ネットワークを通じてデータをシャッフルする必要があり、コストはさらに大きくなります。
ストレージがより安価になるにつれて、人々はフラット化されたモデルを使用し始めています。このモデルでは、処理効率を高めるためにデータが事前に結合されています。次のテーブルは、顧客と注文の情報が 1 つのレコードに保存され、分析の準備ができていることを示しています。
username | name | sex | address | birthdate | transaction_date | shipping_date | items | price | |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/9/14 | 2019/10/12 | 2 | 1237 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/9/16 | 2019/10/9 | 8 | 4824 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/9/17 | 2019/10/10 | 9 | 4392 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/9/17 | 2019/10/9 | 3 | 1079 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/9/25 | 2019/10/7 | 1 | 208 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/10/2 | 2019/10/5 | 10 | 3689 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/10/5 | 2019/10/10 | 7 | 6346 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/10/6 | 2019/10/10 | 5 | 1744 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/10/7 | 2019/10/9 | 2 | 15 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/10/11 | 2019/10/13 | 10 | 4794 |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/10/11 | 2019/10/12 | 7 | 1697 |
palmerpaul | Jennifer Marshall | F | 869 Harrell Forges Apt.111 East Monica, MO 01243 | heather65@hotmail.com | 2007/3/11 | 2019/9/14 | 2019/9/22 | 6 | 4642 |
palmerpaul | Jennifer Marshall | F | 869 Harrell Forges Apt.111 East Monica, MO 01243 | heather65@hotmail.com | 2007/3/11 | 2019/9/17 | 2019/9/21 | 1 | 527 |
palmerpaul | Jennifer Marshall | F | 869 Harrell Forges Apt.111 East Monica, MO 01243 | heather65@hotmail.com | 2007/3/11 | 2019/10/9 | 2019/10/12 | 5 | 408 |
torresdiana | Ashley Hoffman | F | 7815 Lauren Ranch Ambertown, FL 93225 | franklinjonathan@hotmail.com | 1960/5/14 | 2019/9/17 | 2019/9/28 | 9 | 5452 |
このモデルは、分散システムでもうまく機能します。各行には完全な情報が含まれているため、任意のノードで処理でき、データをシャッフルする必要はありません。列形式を使用してデータを保存することもできます。これにより、クエリエンジンは行全体ではなく、必要な列のみを読み取ることができます。この手法により、分析のパフォーマンスが向上し、ストレージ効率が向上します。
どちらのモデルにも長所と短所があります。次元モデルはストレージの効率と計算能力のトレードオフであり、フラット化モデルは処理の効率とストレージのトレードオフです。
両方の長所を実現する新しいデータ型がいくつか利用できます。子レコードを別のテーブルに配置する代わりに、親レコードにネストして、結合を行わずに完全な情報を取得できます。親レコードを複製することなく、データを事実上非正規化します。
次の図は、このワークフローを示しています。
このモデルをスキーマフルな階層データセットに適用できます。顧客と注文の例を続けると、顧客は複数のアイテムを購入する可能性がありますが、各注文アイテムには製品 ID、価格、ベンダーなどの同じタイプの情報が含まれています。
階層は明確で一貫しています。データをネストされた構造化スキーマにマップできます。これは、SQL 言語を介して効率的に保存してアクセスできます。
次のテーブルは、前の例のネストされたデータを表したものです。
username | name | sex | address | birthdate | transaction_date | shipping_date | items | price | |
erin15 | Sarah Newman | F | 795 Nancy Shoal Apt.684 Phillipschester, MI 01979 | josephlyons@yahoo.com | 2010/4/24 | 2019/9/14 | 2019/10/12 | 2 | 1237 |
2019/9/16 | 2019/10/9 | 8 | 4824 | ||||||
2019/9/17 | 2019/10/10 | 9 | 4392 | ||||||
2019/9/17 | 2019/10/9 | 3 | 1079 | ||||||
2019/9/25 | 2019/10/7 | 1 | 208 | ||||||
2019/10/2 | 2019/10/5 | 10 | 3689 | ||||||
2019/10/5 | 2019/10/10 | 7 | 6346 | ||||||
2019/10/6 | 2019/10/10 | 5 | 1744 | ||||||
2019/10/7 | 2019/10/9 | 2 | 15 | ||||||
2019/10/11 | 2019/10/13 | 10 | 4794 | ||||||
2019/10/11 | 2019/10/12 | 7 | 1697 | ||||||
palmerpaul | Jennifer Marshall | F | 869 Harrell Forges Apt.111 East Monica, MO 01243 | heather65@hotmail.com | 2007/3/11 | 2019/9/14 | 2019/9/22 | 6 | 4642 |
2019/9/17 | 2019/9/21 | 1 | 527 | ||||||
2019/10/9 | 2019/10/12 | 5 | 408 | ||||||
torresdiana | Ashley Hoffman | F | 7815 Lauren Ranch Ambertown, FL 93225 | franklinjonathan@hotmail.com | 1960/5/14 | 2019/9/17 | 2019/9/28 | 9 | 5452 |
次のグラフは、3 つのモデルのストレージ使用量を比較しています (すべて parquet 形式で)。
グラフは、ネストされた構造が次元モデルと同じくらい効率的なストレージであることを示しています。
ネストされたデータ型の使用
ネストされたデータ型は、いくつかの一般的なデータパターンの構造化データ型です。ネストされたデータ型は、struct、array、map をサポートします。
struct はリレーショナルテーブルに似ています。オブジェクトのプロパティをグループ化します。たとえば、顧客プロファイルに名前、住所、E メール、誕生日が含まれている場合、次のスキーマとして表示されます。
データは次のコードとして表示されます。
array は 1 対多の関係を保存します。たとえば、顧客が複数の配送先住所または電話番号を持っている場合があります。顧客に複数の電話番号がある場合、次のスキーマとして表示されます。
データは次のコードとして表示されます。
[‘555-5555’, ‘555-1234’]
map は、キーと値のペアのコレクションです。それを struct<key, value> のリストと考えることができます。たとえば、顧客に特定の報酬設定がある場合、次のスキーマとして表示されます。
データは次のコードとして表示されます。
ネストされたデータは、メンバーとして別のネストされたデータ型を持つことができます。最も一般的なものは、struct の配列です。たとえば、注文に複数のアイテムが含まれる場合、次のスキーマとして表示される可能性があります。
それらを組み合わせて、複雑なオブジェクトを作成できます。たとえば、顧客のオンライントランザクションは次のスキーマとして表示されます。
Hive、Spark、Presto、Redshift Spectrum などの一般的なクエリエンジンは、ネストされたデータ型をサポートしています。これらのエンジンは、異なる SQL 構文をサポートする可能性があります。わかりやすく一貫性を保つために、この記事のすべてのクエリ例では Amazon Redshift Spectrum を使用しています。詳細については、「チュートリアル: Amazon Redshift Spectrum でネストされたデータをクエリする」を参照してください。
ネストされたデータ型のユースケース
ネストされたデータ型には、ETL、データモデリングを簡素化し、良好なパフォーマンスを実現するといった多くの利点があります。以下は、ネストされたデータ型の利点を受けられる一般的なユースケースです。
親子関係
ネストされたデータ型は、連結して保存することにより、親子 (要約と詳細) の関係を維持します。多くの場合、これはデータの分析方法と一致します。たとえば、顧客の購買習慣を分析するには、以下を見つける必要がある場合があります。
- 頻繁に購入するが、毎回少数のアイテムのみを購入する顧客。このような顧客はおそらく、送料をカバーする年間メンバーシップを望んでいます。
- あまり頻繁に購入しないが、1 つのトランザクションで多くのアイテムを購入する顧客。このような顧客はおそらく、送料無料の特典や割引を期待しています。
トランザクションごとに顧客が購入するアイテムの平均数など、注文データからのサポート情報が必要です。
少なくとも 1 週間に 1 回、毎回 3 個以下のアイテムをオンラインで注文する顧客のリストを検索するには、次のコードを使用します。
ネストされた注文の詳細では、アイテムごとの情報は、トランザクションごとに顧客を基準としてすでにグループ化されています。子の集約は簡単です。注文の詳細を集計して顧客を分類できます。非正規化テーブルを使用する場合、GROUP BY を 2 回実行する必要があります。クエリにも時間がかかる可能性があります。次のコードを参照してください。
四半期に 1 回のみ、少なくとも 10 個のアイテムを注文し、総支出が多い顧客を見つけるには、次のコードを使用します。
親子データ分析にネストされたデータ型を使用する利点は他にも、リソースの使用量を削減できることがあります。100 万件の顧客トランザクションがある場合、アイテムの注文は 5 倍を超える可能性があります。たとえば、日々ミシガン州に出荷される商品の数を見つけるには、次のコードを使用します。
顧客の 3% が注文をミシガン州に発送すると仮定すると、顧客データをフィルタリングした後、一致するトランザクションが約 3% ある可能性があります。処理する必要がある注文数は 500 万件ではなく、15 万件です。これにより、フラット化モデルと比較して、処理するデータと使用するリソースが大幅に削減されます。
親子のユースケースの場合、ネストされたデータ型により、子の単純な集約、より効率的なフィルタリング、グループ化、ウィンドウ化、ストレージの節約が行えます。
多対多の関係
顧客はさまざまなベンダーから多くのアイテムを購入でき、ベンダーは多くの顧客に製品を販売できます。これは多対多の関係です。
次元モデルでは、customers
テーブル、orders
テーブル、および transactions
テーブルの 3 つのテーブルが必要です。最も多くの顧客を抱えているトップベンダーを見つけるには、3 つのテーブルを結合する必要があります。次のコードを参照してください。
ネストされたデータ型の場合、クエリは次元モデルを使用したクエリに似ています。ただし、注文データは顧客のトランザクションと併置されるため、コストを支払うことなくそれらをオンザフライで結合できます。次のコードを参照してください。
別の例として、ベンダーの Smith PLC は、2019 年 10 月 10 日に大きなセールイベントを開催しました。この販売中に製品を購入した顧客、および最も多額の金額を消費した上位顧客を見つけたいと考えています。そのためには、次のコードを使用します。
次元モデルクエリと比較して、ネストされたモデルは 2〜3 倍高速です。これは、数百万行しかない比較的小さなデータセットです。大規模なデータセットの場合、パフォーマンスの向上はさらに大きく、リソースの使用量は少なくなります。
スパースで頻繁に変更されるデータ
オンラインストアで注文した顧客に報酬を提供するとします。トランザクションごとに、顧客は、送料無料、同日配達、割引、クーポンなどの 1 つ以上の報酬を選択できます。報酬がどれほど効果的かに応じて、報酬の種類を頻繁に変更したり、新しい種類を追加したり、人気のない種類を削除したりする必要があります。
フラット化モデルにデータを保存する場合、このデータを追跡するための 2 つの一般的なオプションがあります。最初の方法は、報酬のタイプごとに 1 つの列を持つテーブルを作成することです。最初に考えられるすべての報酬を考え、列を作成する必要があります。これにより、テーブルが広くなり、データが非常にまばらになる可能性があります。または、報酬タイプを追加または削除するときに、テーブルスキーマを変更できます。これにより、メンテナンス作業が増え、履歴データが失われる可能性があります。次のテーブルは、この方法を示しています (下のテーブルの例のすべての transaction_id データは偽装されています)。
transaction_id | free_shipping | one_day_delivery | discount | coupon |
pklein35966659391853535 | FALSE | TRUE | TRUE | |
rebeccawiliams228880139768961 | FALSE | TRUE | ||
brooke39180013629693040 | TRUE | FALSE | TRUE | TRUE |
jchapman4283556333561927 | FALSE | TRUE | FALSE | FALSE |
mariamartin3515336516983566 | FALSE | FALSE | TRUE |
2 番目のオプションは、行ごとに 1 つの報酬を保存することです。これにより、テーブルが広くなる問題と、スキーマを絶えず更新する負担が回避できます。このアプローチは、単一の報酬のみを分析する必要がある場合に適しています。より多くの顧客が割引やクーポンよりも無料配送と同日配達を好む場合など、報酬間に相関関係があるかどうかを確認したい場合、このオプションは一層複雑です。このモデルには、より多くのストレージも必要です。次のテーブルに、この方法を示します。
transaction_id | rewordtype | value |
pklein35966659391853535 | free_shipping | FALSE |
pklein35966659391853535 | one_day_delivery | TRUE |
pklein35966659391853535 | coupon | TRUE |
rebeccawiliams228880139768961 | one_day_delivery | FALSE |
rebeccawiliams228880139768961 | coupon | TRUE |
brooke39180013629693040 | free_shipping | TRUE |
brooke39180013629693040 | one_day_delivery | FALSE |
brooke39180013629693040 | discount | TRUE |
brooke39180013629693040 | coupon | TRUE |
妥協案は、JSON 文字列を使用して、選択した報酬を 1 つの列にまとめて保存することです。これにより、スキーマの変更が回避されます。次のコードを参照してください。
次のテーブルは、データがどのように JSON 文字列に格納されるかを示しています。
transaction_id | preference |
pklein35966659391853535 | {“coupon”:true, “free_shipping”:false,”one_day_delivery”:true} |
rebeccawiliams228880139768961 | {“coupon”:true, one_day_delivery”:false} |
brooke39180013629693040 | {“coupon”:true, “discount”:true, “free_shipping”:true,”one_day_delivery”:false} |
jchapman4283556333561927 | {“coupon”:false, “discount”:false, “free_shipping”:false, “one_day_delivery”:true} |
mariamartin3515336516983566 | {“discount”:true, “free_shipping”:false,”one_day_delivery”:false} |
JSON 関数を使用して報酬データを抽出することで分析できます。次のコードを参照してください。
このソリューションは受け入れられますが、ネストされたデータ型マップを使用することで、ストレージの効率とパフォーマンスが向上する可能性があります。次のコードを参照してください。
次のテーブルは、データがマップに保存される方法を示しています。
transaction_id | preference |
pklein35966659391853535 | {coupon=true, free_shipping=false,one_day_delivery=true} |
rebeccawiliams228880139768961 | {coupon=true, one_day_delivery=false} |
brooke39180013629693040 | {coupon=true, discount=true, free_shipping=true,one_day_delivery=false} |
jchapman4283556333561927 | {coupon=false, discount=false, free_shipping=false, one_day_delivery=true} |
mariamartin3515336516983566 | {discount=true, free_shipping=false,one_day_delivery=false} |
SQL を使用して、単一または複数の報酬を分析できます。たとえば、送料無料を希望する顧客の数を調べるには、次のコードを使用します。
クーポンや割引よりも無料配送と同日配送を好む顧客の数を調べるには、次のコードを使用します。
マップタイプでは、任意のキーと値のペアを追加できます。スキーマを変更せずにいつでも新しい報酬タイプを追加でき、新しい報酬をすぐに分析できます。
マップタイプの主な利点は、柔軟なスキーマをサポートし、スキーマを頻繁に更新する必要がないことです。ただし、パフォーマンス上の利点はあまりありません。パフォーマンスが最優先事項である場合、フラット化されたテーブルをお勧めします。また、アクセス頻度の高い列をフラット化し、アクセス頻度の低い列にマップを使用することもできます。
ネストされたデータ型の制約
ネストされたデータ型は多くのユースケースで役立ちますが、次の制約があります。
- 子データのサイズには厳しい制限がある。
- 追加のみが可能で、データの更新は難しく、遅い。1 つの子属性を変更する場合でも、ネストされたオブジェクト全体を書き換える必要があります。
- 処理は親レコードレベルで分割される。子データが大きく歪んでいると、問題が発生する可能性があります。
- クエリエンジンは、ネストされたデータのすべてのタイプの分析をサポートしない可能性がある。
- Amazon Redshift Spectrum のネストされたデータの「制約」。
まとめ
この記事では、ネストされたデータ型の利点と、ネストされたデータ型がストレージ効率、パフォーマンスの向上、分析の簡素化に役立つユースケースについて説明しました。ネストされたデータ型が理想的なソリューションになり得るユースケースは他にもたくさんあります。実際にやってみて、どうだったかを教えてください。
著者について
Juan Yu は、AWS のデータウェアハウススペシャリストソリューションアーキテクトです。