Amazon Redshiftの新しいインスタンスタイプ「DS」を試してみた

2015.06.19

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

はじめに

先日、新しい高密度ストレージノード ds2.xlargeとds2.8xlargeの2つのサイズが提供されましたが、価格は据え置きで、vCPU、ECU、メモリ(GiB)、IOが倍ぐらい向上しています。ざっくり倍くらいの性能向上が見られるのではと予想していますが、実際にどれ位の性能向上が見られるか試してみたいと思います。また、移行方法やオトクな情報についてもご紹介いたします。

スペックの新旧比較DS

ds1.xlarge と ds2.xlarge

vCPU ECU メモリ(GiB) ストレージ I/O(GB/s) Network 価格
ds1.xlarge (dw1.xlarge) 2 4.4 15 2TB HDD 0.3 Moderate $1.190/1時間
ds2.xlarge 4 14 31 2TB HDD 0.5 Enhanced $1.190 /1 時間
改善点 2倍 3倍 2倍 2倍 拡張ネットワーキング

dw1.8xlarge と ds2.8xlarge

vCPU ECU メモリ(GiB) ストレージ I/O(GB/s) Network 価格
ds1.8xlarge (dw1.8xlarge) 16 35 120 16TB HDD 2.40GB/s 10 Gbps $9.520/1時間
ds2.8xlarge 36 116 244 16TB HDD 4.00GB/s Enhanced – 10 Gbps $9.520 /1 時間
改善点 2倍 3倍 2倍 2倍 拡張ネットワーキング – 10 Gbps

 

性能検証 - ds1.xlarge vs ds2.xlarge

パフォーマンスの計測条件

  • クエリ性能検証 リージョン:東京リージョン(ap-northeast-1)
  • クラスタ:ds1.xlarge と 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が内部的に実行されます。

ds1.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
時間: 650482.375 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レコード投入しているところがポイントです。

ds1.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
時間: 1867.643 ms

-- 複数行インサート時間 - 7500万レコードをコピー
INSERT INTO lineorder_cp SELECT * FROM lineorder;
INSERT 0 75004738
時間: 90486.852 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が実行されるので一般に時間のかかる処理です。

ds1.xlarge

VACUUM FULL lineorder_cp;
VACUUM
時間: 984606.407 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を実行して、適切なクエリプランが得られるように準備します。

ds1.xlarge

ANALYZE lineorder_cp;
ANALYZE
時間: 32057.025 ms

ds2.xlarge

ANALYZE lineorder_cp;
ANALYZE
時間: 21204.449 ms

行カウント時間の計測

実際のユースケースでは条件付きクエリーを実行して結果を得ることが多いですが、今回はクライアントの実装やネットワークIOで計測値がブレるのを避けるため、行カウントする時間を計測しています。

ds1.xlarge

SELECT COUNT(*) FROM lineorder WHERE lo_custkey < 2000000 and lo_linenumber < 7;
  count
----------
 48223756
(1 行)

時間: 4974.918 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 で、集計テーブルを作成する時間を計測します。

ds1.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
時間: 35.914 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
時間: 49472.154 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

検証結果

これまでの検証結果を御覧頂いたとおり、ds2.xlargeは概ね2倍以上の性能向上が確認できます。特に定期的に実行が必要となるデータロードやVACUUM、集計インサート等が良い結果が得られています。 ds1-vs-ds2

ds1からds2の移行は超簡単

基本的に移行したいクラスタを選択してresizeでds1からds2するだけです。後は全て自動でデータ移行してくれます。 redshift-resize

移行時の補足

  • endpoint 及びリーダーノード Private IPに変更はありません
  • リーダーノードのPublic IPは変更されます
  • 移行している間は、通常よりも負荷が高くなり、データの参照のみ、更新はできません
  • 移行に要する時間は使用済みのディスク量に依存します

【朗報】ds1のRIは乗り換えできます!

Updating your Dense Storage RIs with New Generation DS2 Instances すでにds1(旧dw1)のRI(リザーブドインスタンス)をご購入のお客様には上記のタイトルのメールが届いているので、お気づきかもしれませんが、リザーブドインスタンスを移行できます。ds2のリザーブドインスタンス再購入していただくことが前提で、ds1のリザーブドインスタンスをキャンセルして移行します。(弊社「クラスメソッド・メンバーズ」加入のお客様はご相談ください)

最後に

これまで、CPUとIOのどちらかが上限に達すると性能が頭打ちになっていましたが、CPUとIOが共に2倍以上になったことで全ての検証項目において圧倒的に良い結果が得られました。 現在ds1(旧dw1)をご利用中の皆さんがds2に移行するための条件は全て整いましたので、ぜひご検討ください。