Amazon Redshift エントリーノードタイプ dc1.large と ds2.xlarge の徹底比較

2015.06.30

はじめに

先日、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よりも高いコンピュート性能が得られることが試算できます。

dc1vsds2

最後に

データの容量が480GB未満で済む場合は、dc1.largeの3ノードクラスタ構成にすることで、ds2.xlargeよりも安く高性能なDWHを手に入れることができます。一方、価格を抑え、2TBのデータ容量が必要な場合は、ds2.xlargeから始めていただくことが良いでしょう。いずれのインスタイプを選択したとしても、マネジメントコンソールからノードタイプやノード数を変更するだけで、バックエンドでの自動的なデータ移行・新旧の切替等、全て自動でアップサイジング・ダウンサイジングされますのでご安心ください。