ちょっと話題の記事

Amazon Redshift DB開発者ガイド – システム概要

2013.08.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

redshift-db-dev-guide

Amazon Redshiftデータウェアハウスは、エンタープライズクラスのリレーショナル・データベースクエリと管理システムです。

Amazon Redshiftはビジネス・インテリジェンス(BI)、レポート、データ、分析ツール等を含む多くの種類・タイプのアプリケーションを用いてのクライアント接続をサポートしています。分析クエリを実行する際は、取得や比較、及び最終結果を生成する為に複数段階操作で大量のデータを評価しています。

Amazon Redshiftは、効率的なストレージと超並列処理、柱状データストレージ、及び非常に効率的な、ターゲットを絞ったデータの圧縮符号化方式の組み合わせにより、最適なクエリのパフォーマンスを実現します。このセクションでは、Amazon Redshiftのシステムアーキテクチャの概要を提示し、データベースの設計、パフォーマンスを最大化するためのアーキテクチャを活用してクエリを記述する方法について説明します。

目次

 

データウェアハウスシステムアーキテクチャ

以下図に示すように、このセクションでは、Amazon Redshiftデータウェアハウス・アーキテクチャの要素をご紹介します。

02-NodeRelationships

クライアントアプリケーション(Client Appilcations)

Amazon Redshiftは、様々なデータロードやETL(Extract:抽出、Transform:変換、Load:ロード)ツール、ビジネス・インテリジェンス(BI)レポート、データマイニング、分析ツールと統合されています。Amazon Redshiftは業界標準のPostgreSQLに基づいているので、殆どの既存SQLクライアント・アプリケーションは最小限の変更で動作します。Amazon RedshiftSQLとPostgreSQLの重要な相違点については、Amazon Redshift and PostgreSQLを参照してください。

接続(Connections)

Amazon Redshiftは、業界標準のPostgreSQLのJDBCとODBCドライバを使用して、クライアントアプリケーションと通信します。詳細についいては、Amazon Redshift and PostgreSQL JDBC and ODBCをご参照ください。

クラスタ(Clusters)

Amazon Redshiftの中核となるインフラストラクチャコンポーネントは、クラスタです。

クラスタは、1つ以上の計算ノードで構成されています。もしクラスタが2つ以上の計算ノードでプロビジョニングされている場合、追加のリーダーノードは計算ノードを調整し、外部との通信を処理します。クライアントアプリケーションはリーダーノードと直接対話します。計算ノードは、外部のアプリケーションに対して透過的です。

リーダーノード(Leader Node)

リーダーノードは、クライアントプログラムと計算ノードとの全ての通信を管理します。データベース操作(特に複雑なクエリの結果を得る為に必要な一連のステップ)を行う為の実行計画を解析し、現像します。実行計画に基づき、リーダーノードはコードをコンパイルし、計算ノードにコンパイルされたコードを配布し、各計算ノードへデータの一部を割り当てます。

クエリが計算ノードに格納されているテーブルを参照している場合にのみ、リーダーノードはSQLステートメントを計算ノードに配布します。他の全てのクエリは、リーダーノード上で排他的に実行されます。Amazon Redshiftはリーダーノード上で特定のSQL関数を実装する為に設計されています。これらの関数を使用するクエリは計算ノードに存在するテーブルを参照する場合、エラーを返します。詳細については、SQL functions supported on the leader nodeをご参照ください。

計算ノード(Compute Nodes)

リーダーノードは、実行計画の個々の要素のためのコードをコンパイルし、個々の計算ノードにコードを割り当てます。計算ノードは、最終的な集約のためにリーダーノードに戻った中間結果を送信された、コンパイルされたコードを実行します。

各計算ノードは、専用のCPU、メモリ、アタッチされたディスクストレージを持っており、それらはノードタイプによって決定されています。作業負荷が大きくなるにつれて、ノードタイプ、またはその両方をアップグレードさせてノード数を増やす事により、計算能力及びクラスタの記憶容量を増加させる事が出来ます。

Amazon Redshiftは2つのノードタイプを提供します。

  • 2コア XLノード/15GiBメモリ/2TBのローカルストレージ/3ディスクドライブ
  • 16コア 8XLノード/120GiBメモリ/16TBのローカルストレージ/24ディスクドライブ

あなたは単一の2TB XLノードで使い始め、ペタバイト以上のデータをサポートする為に復数の16TB 8XLノードまでそれらを拡張する事が出来ます。データウェアハウス・クラスター及びノードの詳細な説明については、Internal architecture and system operationをご参照ください。

ノードスライス(Node slices)

計算ノードはノードのマルチコアプロセッサの各コア用のスライスに分割され、各スライスは、ノードに割り当てられた作業負荷の一部を処理するノードのメモリとディスク領域の一部を割り当てられます。リーダーノードは、スライスと配分するスライスへの質問や他のデータベース操作のためのワークロードに配布するデータを管理します。スライスはそれらの操作を完了させるために、並行して作業を行います。

テーブル作成時には、必要に応じて"分散キー"として1つの列を指定する事が出来ます。データがテーブルにロードされると、行がテーブルに定義されている配布キーに従い、ノードのスライスに分配されます。適切に分散キーを選択すると、Amazon Redshiftはデータをロードし、効率的にクエリ実行を並列処理してくれます。分散キーの選択については、Choosing the best distribution keyをご参照ください。

内部ネットワーク(Internal Network)

Amazon Redshiftは、プライベート且つ(リーダーノードと計算ノード間の)非常に高速なネットワーク通信を提供する為に広帯域幅の接続、近接、そしてカスタム通信プロトコルを利用します。計算ノードは、クライアントアプリケーションが直接アクセスしない、独立・分離されたネットワーク上で実行されます。

データベース(Databases)

クラスタは、1つ以上のデータベースを含んでおり、ユーザーデータは、計算ノードに格納されています。SQLクライアントは順番に計算ノードとクエリ実行を調整しているリーダーノードと通信します。

Amazon Redshiftはリレーショナルデータベース管理システム(RDBMS)である為、他のRDBMSとも互換性があります。データの挿入、削除等オンライントランザクション管理(OLTP)の機能を含む典型的なRDBMSと同等の機能を提供しますが、Amazon Redshiftは非常に大規模なデータセットの高性能な分析とレポートの為に最適化されています。

Amazon RedshiftはPostgreSQL 8.0.2に基づいています。Amazon RedshiftとPostgreSQLには非常に多くの重要な相違点があります。それらについて、あなたはデータウェアハウスアプリケーションを設計・開発する際に考慮する必要があります。Amazon RedshiftのSQLがPostgreSQLのSQLとどう違うのかについては、Amazon Redshift and PostgreSQLをご参照ください。

 

パフォーマンス

Amazon Redshiftは、以下のパフォーマンス機能を使用する事によって、非常に高速なクエリの実行を実現します。

  • 超並列処理
  • カラムナ型データストレージ
  • データ圧縮
  • クエリの最適化
  • コンパイル済みコード

超並列処理

超並列処理(MPP)は、大量のデータで動作する最も複雑なクエリの高速実行を可能とします。復数の計算ノードが、各ノードの各コアが同一のコンパイルされたクエリセグメントを実行しながら最終集計結果に至るまでの全てのクエリ処理を扱います。

Amazon Redshiftは、データを並列に処理出来るように、計算ノードにテーブルの行を分散しています。テーブル毎に適切な分散キーを選択する事により、 作業負荷のバランスを取り、ノードからノードへのデータ移動を最小限に抑える為にデータ分散を最適化する事が出来ます。

詳細については、Choosing the best distribution key

フラットファイルからのデータのロードは、同時に復数のファイルからの読み取り中に、復数のノード間でワークロードを分散する事によって並列処理を利用しています。テーブルにデータをロードする方法の詳細については、 Best practices for loading dataをご参照ください。

カラムナ型データストレージ

データベーステーブルのカラムナ型ストレージは、大幅に全体的なディスクI/O要件を低減させ、分析クエリのパフォーマンスを最適化する上での重要な要因となっています。円柱状にデータベーステーブル情報を格納する事により、ディスクI/O要求の数及びディスクからロードする必要のあるデータの量を減らします。

メモリに少量のデータをロードすると、Amazon Redshiftはクエリ実行の際にそれらに対してより多くのメモリを割り当てて実行する事が出来ます。より詳細な説明についてはColumnar storage for a more detailed explanationをご参照ください。

列が適切にソートされていると、クエリプロセッサはデータブロックの大規模なサブセットを速やかに除外する事が出来ます。詳細についてはChoosing the best sort keyをご参照ください。

データ圧縮

データ圧縮は、クエリのパフォーマンスを向上させるディスクI/Oの削減 によってストレージの要件を低減します。 クエリを実行すると、圧縮されたデータはメモリに読みこまれ、そしてクエリ実行時に解凍されます。 メモリに少量のデータをロードすると、Amazon Redshiftはデータを分析する事により多くのメモリを割り当てる事が出来ます。 カラムナ型ストレージが類似したデータを順次格納しているので、Amazon Redshiftは圧縮エンコーディングを(特にカラムナ型データタイプのものに対して)適用する事が出来ます。

表の列に対してデータ圧縮を有効にするための最善の方法は、Amazon Redshiftがデータを持つテーブルをロードする場合に最適な圧縮符号化処理を適用出来るようにする事です。自動データ圧縮を使用する方法の詳細については、Loading tables with automatic compression.をご参照ください。

クエリの最適化

Amazon Redshiftのクエリ実行エンジンは超並列処理(MPP)に対応しているクエリオプティマイザを搭載しており、またカラムナ型指向データストレージを利用しています。

Amazon Redshiftのクエリオプティマイザは、複素解析クエリを処理する為の大幅な機能強化と実装拡張を行なっています。クエリの最適化詳細については、Tuning Query Performanceをご参照ください。

コンパイル済みコード

リーダーノードは、クラスタ全てのノード全体で完全に最適化されたコンパイル済みのコードを配布しています。クエリをコンパイルすると、変換に関連するオーバーヘッドが排除され、特に複雑なクエリに対しては結果として実行速度が向上します。コンパイルされたコードはキャッシュされ、同じクラスタ上のセッション間で共有されるので、同様のクエリ実行を行う後続処理では(パラメータが異なっていたとしても)高速になります。

実行エンジンは、接続プロトコルのJDBC接続プロトコル及びODBCとpsql(libq)毎に異なるコードをコンパイルし、異なるプロトコルを使用するので、2つのクライアントがそれぞれのコードをコンパイルする際に始めてコストが掛かります。しかし、同じプロトコルを使用する他のクライアントにとっては、キャッシュされたコードを共有する恩恵を受ける事が出来るでしょう。

 

カラムナストレージ

データベーステーブルのカラムナストレージは、大幅に全体的なディスクI/O要求を低減し、ディスクからロードする必要のあるデータの量を減少させるので、分析クエリパフォーマンスを最適化する上でとても重要な要素です。以下の一連の図は、 カラムナデータストレージがどのようにして、効率化の部分を実装しているのか、また、メモリにデータを取り込む際、どのようにしてその辺りの効率化の部分を変換しているのか、と言った点について表しています。この最初の図は、データベーステーブルからレコードが行によってディスクブロックに格納される方法を示しています。

03a-Rows-vs-Columns

典型的なリレーショナルデータベースのテーブルでは、各行は、単一レコードのフィールド値が含まれています。行方向データベースストレージでは、各々順次連続した列のデータブロックストアの値が行全体を構成しています。

  • ブロックサイズがレコードのサイズより小さい場合、レコード全体のストレージは複数のブロックを取る事が出来ます。
  • ブロックサイズがレコードのサイズより大きい場合、レコード全体のストレージ容量はレコード全体に対するストレージ容量は、1つのブロックより少ないものになってしまうかもしれず、ディスク領域を非効率な形で使う結果になってしまうかもしれません。

オンライントランザクション処理(OLTP)アプリケーションでは、殆どのトランザクションが一度に1レコード、又は少ない件数のレコードの処理に対してレコード全体に対して値全体を読み書きしています。結果としては行方向ストレージはOLTPデータベースに適しています。

03b-Rows-vs-Columns

複数行の単一列の各データブロックが格納された、カラムナストレージを使います。レコードがシステムを入力すると、Amazon Redshiftは透過的に各列のカラムナストレージにデータを変換します。

この簡単な例では、カラムナストレージを利用して、各データブロックが 行ベースの3倍の列フィールドの値を保持しています。これは、同じレコード番号の列フィールドの同じ数の値を読み出す事は行単位ストレージに比べてI/O操作が3倍掛かると言う事を意味します。実際には、非常に大きな行数、列数のテーブルを利用すると、ストレージ効率は更に大きくなります。

追加の利点としては、各ブロックは同じタイプのデータを保持しているので、ブロックデータは列のデータ型の為に選択された圧縮方式を使用する事が出来、更にディスク容量とI/Oを削減出来ます。データタイプに基づく圧縮エンコーディングの詳細については、Compression encodingsをご参照ください。

ディスク上のデータを格納する為のスペースの節約はまた、取得した後にメモリ内のデータを格納するために引き継がれます。多くのデータベース操作が1つ若しくは少数のカラム程度しか処理に必要としないので、あなたが実際にクエリに必要な列のためのブロックを取得する事により、メモリ空間を節約する事が出来ます。

OLTPトランザクションが、殆どまたは少数のレコード行の全ての列に関与するような場面では、データウェアハウスのクエリは一般的に非常に多数の行に対し、幾つかの列を読み取ります。これは、同じ行数に対して同じ数の列の値を読む事はI/O操作の一定の割合を必要とし、行方向のブロックを処理する為に必要とされるメモリの一部を使用するという事を意味します。

実際には、非常に大きな数の列及び行のテーブルを使うことで、効率化の向上が比例して大きくなります。例えば、テーブルに100個の列が含まれているとします。5つの列を使用するクエリは、テーブルに含まれるデータの5%について読み込む必要があります。この節約は、大規模なデータベースのレコードの恐らく何十億、あるは何兆にも渡って繰り返されます。これとは対照的に、行方向データベースも95の不要な列を含むブロックを読んでいました。

典型的なデータベースブロックサイズは2KBから32KBに及びます。Amazon Redshiftは、より効率的であり、更にクエリ実行の一部である任意のデータベースのロード、また他の操作を実行する為に必要なI/O要求の数を減らす1MBのブロックサイズを使用します。

 

内部アーキテクチャとシステム運用

以下は内部コンポーネントとAmazon Redshiftのデータウェアハウスの機能性を示す概要図となります。

05-InternalComponents

クエリ実行

実行エンジンは、どのようにSQLクエリや他のデータベース操作がクラスタによって計画・実行され、結果やステータスがクライアントに送り返されるかを制御します。

セクションでは、Amazon Redshiftクエリ処理の概要を説明します。詳細については、Tuning Query Performanceをご参照ください。

クライアント要求と実行

以下は、クエリの計画と実行ワークフローの概要図となります。

07-QueryPlanning

1.Parser

SELECT, UPDATE, INSERTまたはDELETEステートメントを含む新しいリクエストが到着すると、リーダーノード、パーサーに要求を渡します。パーサーはまた、AS CREATE TABLEのようにSELECT句を含む文を処理します。

2.Query Tree

パーサーは、初期の問い合わせツリーを生成します。この問い合わせツリーは、元のクエリまたはステートメントの論理表現です。問い合わせツリーの内容は、クエリ実行計画を策定する為に使用する物理的な計画を実行するAmazon Redshiftオプティマイザへの入力として使われます。

3.Logical transformation

オプティマイザはこのような述語プッシュ、相関サブクエリの最適化、排除、共通部分式の最適化、及び幾つかの他のプロセスを組み込みつつ、クエリの書き換えを行います。

4.Query Plan

最終問い合わせツリーは、クエリプランに変換されます。クエリプラン作成はハッシュ結合、マージ結合、集計計画などのようなクエリプラン作成方法及び処理ステップを使用するかどうかを決定する事を含みます。

クエリプランを表示したり、計画を説明する為に、EXPLAINコマンドを使用する事が出来ます。これはクエリプランを分析し、複雑なクエリをチューニングするための基本的なツールです。クエリを最適化する為の実行計画を使用する方法の詳細については、Analyzing the query planをご参照ください。

5.Execution engine

実行エンジンは、オプティマイザによって提供されるクエリプランを実行するために、ステップ・セグメント・及びストリームのシーケンスをアセンブルします。

次に、計算ノードで実行出来るように、C++のコードを生成し、コンパイルします。コンパイルされたコードは、解釈済みのコードよりも遥かに高速に実行され、計算能力も少なく済みます。最初の実行時間はコードをコンパイルする為のオーバーヘッドが含まれている為、クエリをベンチマークする際は、2回目の実行時間を比較対象にする必要があります。

詳細については、Benchmarking with compiled codeをご参照ください。

6.Compute nodes

実行エンジンは、計算ノードの各々にストリームに対応する実行可能なコードを送信します。

Amazon Redshiftの問い合わせ実行パフォーマンスに対する1つの"鍵"は、ノードのスライスのそれぞれ個別の問い合わせプロセスが並行してコンパイルされたクエリのコードを実行する、という事実です。

また、Amazon Redshiftはクエリプランの段階から次の中間結果を渡す為に、最適化されたネットワーク通信、メモリ、ディスク管理を活用しています。これは、クエリの実行を高速化するのに役立ちます。

計画

以下例は、SQLクエリ、及びAmazon Redshiftがクエリを実行するために必要な、論理的な手順を示す為に作成した実行計画です。ボトムアップの実行計画を読み取る事で、それらの相対的なコスト及び処理する必要のあるデータ量の指標として、クエリを実行する為に必要な論理演算の内訳を見る事が出来ます。クエリプランを分析する事で、あなたは多くのケースで、クエリのパフォーマンスを向上させる為のきっかけを掴む事が出来るでしょう。

select eventname, sum(pricepaid) from sales, event
where sales.eventid = event.eventid
group by eventname
order by 2 desc;
QUERY PLAN
XN Merge  (cost=1000451920505.33..1000451920506.77 rows=576 width=27)
  Merge Key: sum(sales.pricepaid)
  ->  XN Network  (cost=1000451920505.33..1000451920506.77 rows=576 width=27)
        Send to leader
        ->  XN Sort  (cost=1000451920505.33..1000451920506.77 rows=576 width=27)
              Sort Key: sum(sales.pricepaid)
              ->  XN HashAggregate  (cost=451920477.48..451920478.92 rows=576 width=27)
                    ->  XN Hash Join DS_DIST_INNER  (cost=47.08..451920458.65 rows=3766 width=27)
                          Inner Dist Key: sales.eventid
                          Hash Cond: ("outer".eventid = "inner".eventid)
                          ->  XN Seq Scan on event  (cost=0.00..87.98 rows=8798 width=21)
                          ->  XN Hash  (cost=37.66..37.66 rows=3766 width=14)
                                ->  XN Seq Scan on sales  (cost=0.00..37.66 rows=3766 width=14)

実行計画を読み込む方法の詳細については、Analyzing the explain planをご参照ください。

クエリの実行ステップ

実行計画の生成の一環として、クエリオプティマイザはストリーム、セグメント、及びデータとクエリワークロード計算ノードへの配布の準備の為に、幾つかのステップ計画を分解します。テーブル設計の一部として指定する列制約、ソートキー、及び分散キーによってクエリのパフォーマンスを向上させる事が出来るかどうかを検討する為に、システムビューで実行計画を確認する事が出来ます。実行計画を調べる事によって、また、クエリを書き換える事で、クエリのパフォーマンスを改善出来る事が出来るかもしれません。

以下の図では、クエリオプティマイザが実行計画の論理演算を、Amazon Redshiftが計算ノードのスライス用にコンパイルされたコードを生成する為に使っているストリームやセグメント、ステップに変換する方法を示す為に、前の例での実行計画を用いて示しています。

09-QueryExecutionSteps

Step

それぞれのステップは、実行計画の個々の操作です。ステップは、計算ノードがクエリや結合、または他のデータベース操作を実行出来るように組み合わせる事が出来ます。

Segment

単一のプロセスによって行う事が出来る、幾つかのステップの集合。セグメントはまた、計算ノードで単一のコンパイル単位で実行が可能です。各セグメントはテーブルデータのSCANから始まり、具体化ステップ又は他のネットワーク活動のいずれかによって終了します。

Stream

常に幾つかのデータセットのSCANで始まり、具体化若しくはブロッキングのステップで終わるセグメントのコレクション。マテリアやブロッキングのステップはHASH、AGG、SORT,及びSAVEが含まれます。

クエリの最後のセグメントはデータを返します。もし返り値が設定又はソートされている場合、計算ノードはリーダーノードに中間結果それぞれを送ります。リーダーノードはデータをマージし、最終結果は要求を行っているクライアントに結果を返す事が出来るようになります。

実行計画で使用される演算子の詳細については、EXPLAIN operatorsをご参照ください。

作業負荷管理

Amazon Redshiftワークロード管理(Workload Management:WLM)を使う事で、ユーザが柔軟に優先順位を管理する事が可能となります。その短いワークロード内で、高速に実行されるクエリは実行時間の長いクエリの後ろのキューに溜まってしまう事はなくなります。Amazon Redshift WLMはサービスクラスに応じて、実行時に照会のキューを作成します。サービスクラスでは、内部システムキューとユーザーがアクセス可能なキューを含む様々なキューのタイプに対する設定パラメータを定義しています。

ユーザーの観点から見ると、ユーザーがアクセス可能なサービスクラスとキューは機能的に同等です。一貫性を保つため、このドキュメントではユーザーがアクセス可能なサービスクラスと同様にランタイムキューを意味するターム(term)キューを使用します。

クエリを実行すると、ユーザーのユーザーグループまたはユーザーが実行時に設定したクエリグループラベルと、キュー構成にリストされているクエリグループを照合する事によって、WLMはクエリをキューに割り当てます。

デフォルトでは、Amazon Redshiftは1つのキューに対して5段階の並行処理レベルを設定します。また、8つのキューを定義する事が出来ます。各キューは最大同時実行レベル:15まで構成する事が出来ます。全てのユーザー定義のキューの最大合計同時実行レベルが15、という事です。

WLM構成を変更する最も簡単な方法は、Amazon Redshiftの管理コンソールを使う事です。また、Amazon Redshiftのコマンドラインインタフェース(CLI)またはAPIを使用する事が出来ます。

ワークロード管理を実装・使用する方法の詳細については、Implementing workload managementをご参照ください。

まとめ

以上、ドキュメントのシステム概要に当たる部分を読み進めてみました。Redshift自体の理解度がまだ低いのと翻訳内容によって若干読み辛い、意味が不明瞭となっている箇所があるかもしれませんが、ご了承頂ければと思います。随時改善を加えて読み易い内容にして行ければと思います。また、文中詳細情報を展開している部分についても、片っ端から読み解いて行こうと思いますのでよろしくお願いします。

参考情報