Amazon Redshift エントリーノードタイプ dc1.large と ds2.xlarge の徹底比較
はじめに
先日、Amazon Redshiftの新しいノードタイプ ds2.xlarge と ds2.8xlarge がリリースされました。Amazon Redshiftの新しいインスタンスタイプ「DS」を試してみた でご報告したとおり、従来のds1.xxx(dw1.xxx)から約2倍以上のコンピュート性能の向上が確認できました。そこで気になるのが、現行の高密度コンピュートノード dc1.large や dc1.8xlarge の使い分けになります。
本日はエントリーインスタンスである高密度コンピュートノード dc1.large と先日リリースされた新しい高密度ストレージノード ds2.xlarge の 2つをスペックと性能の観点で比較してみたいと思います。
dc1.large と ds2.xlarge の違い
高密度コンピュートノード dc1.large
Dense Compute(DC)ノードでは、安価で高パフォーマンスのデータウェアハウスを作成できるように、高速 CPU、大容量 RAM、および SSD(Solid-State Disk)が使用されます。ディスク容量よりもIOや処理性能を重視したノードタイプで、上位のノードタイプとしてdc1.8xlargeが提供されています。dc1.largeはRedshiftが提供する最も利用費が安いノードタイプです。
Node Size | vCPU | ECU | Memory (GiB) | Storage | Node Range | Total Capacity |
---|---|---|---|---|---|---|
dc1.large | 2 | 7 | 15 | 160 GB SSD | 1–32 | 5.12 TB |
dc1.8xlarge | 32 | 104 | 244 | 2.56 TB SSD | 2–128 | 326 TB |
高密度ストレージノード ds2.xlarge
新しい Dense Storage(DS)ノードでは、従来(ds1)よりも高パフォーマンスのデータウェアハウスを作成できるように、CPU、RAM、IOがそれぞれ2倍以上の向上し、大容量のHDD(ハードディスク)が使用されます。コンピュート性能よりもデータ容量を重視したノードタイプで、上位のノードタイプとしてds2.8xlargeが提供されています。といいましてもds1.xlarge は dc1.large 以上にコンピュート性能が優れています。
de Size | vCPU | ECU | RAM (GiB) | Storage | Node Range | Total Capacity |
---|---|---|---|---|---|---|
ds2.xlarge | 4 | 13 | 31 | 2 TB HDD | 1–32 | 64 TB |
ds2.8xlarge | 36 | 119 | 244 | 16 TB HDD | 2–128 | 2 PB |
dc1.large と ds2.xlarge のスペックの比較
vCPU | ECU | メモリ(GiB) | ストレージ | I/O(GB/s) | Network | 価格 | |
---|---|---|---|---|---|---|---|
dc1.large (dw2.large) | 2 | 7 | 15 | 0.16TB SSD | 0.2 | Enhanced | $0.314 /1 時間 |
ds2.xlarge | 4 | 14 | 31 | 2TB HDD | 0.5 | Enhanced | $1.190 /1 時間 |
スペック比較 | 2倍 | 2倍 | 2倍 | 12.5倍 | 2.5倍 | ー | 4倍 |
性能検証 - dc1.large vs ds2.xlarge
パフォーマンスの計測条件
- クエリ性能検証 リージョン:東京リージョン(ap-northeast-1)
- クラスタ:dc1.large と ds2.xlarge ともに single node
- データ:AWSが提供しているサンプルデータ(s3://awssampledbapnortheast1/ssbgz/lineorder0000_part_00.gz)
- レコード数:7500万レコード
- テーブル:lineorder
CREATE TABLE lineorder ( lo_orderkey INTEGER NOT NULL, lo_linenumber INTEGER NOT NULL, lo_custkey INTEGER NOT NULL, lo_partkey INTEGER NOT NULL, lo_suppkey INTEGER NOT NULL, lo_orderdate INTEGER NOT NULL, lo_orderpriority VARCHAR(15) NOT NULL, lo_shippriority VARCHAR(1) NOT NULL, lo_quantity INTEGER NOT NULL, lo_extendedprice INTEGER NOT NULL, lo_ordertotalprice INTEGER NOT NULL, lo_discount INTEGER NOT NULL, lo_revenue INTEGER NOT NULL, lo_supplycost INTEGER NOT NULL, lo_tax INTEGER NOT NULL, lo_commitdate INTEGER NOT NULL, lo_shipmode VARCHAR(10) NOT NULL ) distkey(lo_orderkey) sortkey(lo_orderdate, lo_custkey);
データロード時間の計測
まずは他のデータソースからRedshiftにデータをロード(COPYコマンド)する時間を計測します。以下の処理ではデータのロード、VACUUM、ANALYZEが内部的に実行されます。
dc1.large
COPY lineorder FROM 's3://awssampledbapnortheast1/ssbgz/lineorder0000_part_00.gz' CREDENTIALS 'aws_access_key_id=xxx;aws_secret_access_key=yyy;token=ccc' GZIP; INFO: Load into table 'lineorder' completed, 75004738 record(s) loaded successfully. COPY 時間: 381238.196 ms
ds2.xlarge
COPY lineorder FROM 's3://awssampledbapnortheast1/ssbgz/lineorder0000_part_00.gz' CREDENTIALS 'aws_access_key_id=xxx;aws_secret_access_key=yyy;token=ccc' GZIP; INFO: Load into table 'lineorder' completed, 75004738 record(s) loaded successfully. COPY 時間: 269101.802 ms
一数行インサート・複数行インサート時間の計測
Redshiftでは、空のテーブルに対して INSERT INTO ... SELECT でデータを投入するとソート済みデータとして投入できますが、後ほどVACUUM時間を計測したいので、ソート状態にならないように事前に1レコード投入しているところがポイントです。
dc1.large
-- 一行インサート時間 - 100%非ソート状態とするため先頭にわざと1レコード追加 INSERT INTO lineorder_cp VALUES(1,1,1,1,1,1,'9','8',1,1,1,1,1,1,1,1,'7'); INSERT 0 1 時間: 669.886 ms -- 複数行インサート時間 - 7500万レコードをコピー INSERT INTO lineorder_cp SELECT * FROM lineorder; INSERT 0 75004738 時間: 78671.751 ms
ds2.xlarge
-- 一行インサート時間 - 100%非ソート状態とするため先頭にわざと1レコード追加 INSERT INTO lineorder_cp VALUES(1,1,1,1,1,1,'9','8',1,1,1,1,1,1,1,1,'7'); INSERT 0 1 時間: 736.959 ms -- 複数行インサート時間 - 7500万レコードをコピー INSERT INTO lineorder_cp SELECT * FROM lineorder; INSERT 0 75004738 時間: 42181.881 ms
※ lineorder_cpテーブルのソート割合(sort_percentage)0(0%)の状態であることを確認
status | tablename | sorted_rows | rows | sort_percentage --------------+---------------------+-------------+----------+----------------- 1_sorted | lineorder_cp | 1 | 75004739 | 0.000 1_sorted | lineorder | 75004738 | 75004738 | 1.000
VACUUM時間の計測
7500万レコードのデータに対してVACUUM FULLを実行します。内部的にDELETE、SORTが実行されるので一般に時間のかかる処理です。
dc1.large
VACUUM FULL lineorder_cp; VACUUM 時間: 648328.563 ms
ds2.xlarge
VACUUM FULL lineorder_cp; VACUUM 時間: 360415.435 ms
※ lineorder_cpテーブルのソート割合(sort_percentage)1.0(100%)の状態であることを確認
status | tablename | sorted_rows | rows | sort_percentage --------------+---------------------+-------------+----------+----------------- 1_sorted | lineorder_cp | 75004739 | 75004739 | 1.000 1_sorted | lineorder | 75004738 | 75004738 | 1.000
ANALYZE時間の計測
VACUUMをかけたことに加え、INSERT INTO ... SELECT で投入したデータに対してANALYZEが実行されていませんので、テーブルをANALYZEを実行して、適切なクエリプランが得られるように準備します。
dc1.large
ANALYZE lineorder_cp; ANALYZE 時間: 16251.905 ms
ds2.xlarge
ANALYZE lineorder_cp; ANALYZE 時間: 21204.449 ms
行カウント時間の計測
実際のユースケースでは条件付きクエリーを実行して結果を得ることが多いですが、今回はクライアントの実装やネットワークIOで計測値がブレるのを避けるため、行カウントする時間を計測しています。
dc1.large
SELECT COUNT(*) FROM lineorder WHERE lo_custkey < 2000000 and lo_linenumber < 7; count ---------- 48223756 (1 行) 時間: 2047.460 ms
ds2.xlarge
SELECT COUNT(*) FROM lineorder WHERE lo_custkey < 2000000 and lo_linenumber < 7; count ---------- 48223756 (1 行) 時間: 3330.948 ms
集計インサート時間の計測
DWHでは、ビックデータに対して1次集計、2次集計...マート作成等の集計テーブルの作成が日常的に行われますので、集計をして INSERT INTO ... SELECT で、集計テーブルを作成する時間を計測します。
dc1.large
CREATE TABLE lineorder_summary ( lo_linenumber INTEGER NOT NULL, lo_custkey INTEGER NOT NULL, lo_ordertotalprice INTEGER NOT NULL ) distkey(lo_custkey) sortkey(lo_ordertotalprice, lo_linenumber, lo_custkey); CREATE TABLE 時間: 92.200 ms INSERT INTO lineorder_summary SELECT lo_linenumber, lo_custkey, SUM(lo_ordertotalprice) as lo_ordertotalprice FROM lineorder_cp GROUP BY lo_linenumber, lo_custkey ORDER BY lo_ordertotalprice, lo_linenumber, lo_custkey; INSERT 0 13094201 時間: 38661.090 ms
ds2.xlarge
CREATE TABLE lineorder_summary ( lo_linenumber INTEGER NOT NULL, lo_custkey INTEGER NOT NULL, lo_ordertotalprice INTEGER NOT NULL ) distkey(lo_custkey) sortkey(lo_ordertotalprice, lo_linenumber, lo_custkey); CREATE TABLE 時間: 155.345 ms INSERT INTO lineorder_summary SELECT lo_linenumber, lo_custkey, SUM(lo_ordertotalprice) as lo_ordertotalprice FROM lineorder_cp GROUP BY lo_linenumber, lo_custkey ORDER BY lo_ordertotalprice, lo_linenumber, lo_custkey; INSERT 0 13094201 時間: 22612.040 ms
性能の検証結果
計測した結果、dc1.large のAWS利用費は ds2.xlargeの1/4程度ですが、コンピュート性能は1/2程度です。つまり、dc1.largeを2ノードクラスタ構成にすると、AWS利用費は1/2でds2.xlargeよりも高いコンピュート性能が得られることが試算できます。
最後に
データの容量が480GB未満で済む場合は、dc1.largeの3ノードクラスタ構成にすることで、ds2.xlargeよりも安く高性能なDWHを手に入れることができます。一方、価格を抑え、2TBのデータ容量が必要な場合は、ds2.xlargeから始めていただくことが良いでしょう。いずれのインスタイプを選択したとしても、マネジメントコンソールからノードタイプやノード数を変更するだけで、バックエンドでの自動的なデータ移行・新旧の切替等、全て自動でアップサイジング・ダウンサイジングされますのでご安心ください。