Amazon Redshift 最適な分散スタイルを自動設定する『DISTSTYLE AUTO』の動きを確認してみました

2018年の11月のCluster Version Historyに記載のあった『DISTSTYLE AUTO』がついに利用できるようになりました。分散スタイルに`AUTO`を指定すると最適な分散スタイルを自動的かつ動的に設定する新機能です。リリースバージョン 1.0.6754 以降で利用可能になりましたので、実際にテーブルを作成してどのように自動的かつ動的に設定が変化するかを確認したいと思います。
2019.05.01

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

はじめに

2018年の11月のCluster Version Historyに記載のあった『DISTSTYLE AUTO』がついに利用できるようになりました。分散スタイルにAUTOを指定すると最適な分散スタイルを自動的かつ動的に設定する新機能です。リリースバージョン 1.0.6754 以降で利用可能になりましたので、実際にテーブルを作成してどのように自動的かつ動的に設定が変化するかを確認したいと思います。

分散スタイルAUTO(DISTSTYLE AUTO)とは

分散スタイルがAUTOの場合、最適な分散スタイルを自動的かつ動的に設定する新機能です。これまでは分散スタイルを指定しない場合のデフォルトはEVENでしたが、今後はAUTOになります。これまで分散スタイル指定せずにテーブルを作成していた方はデフォルトの分散スタイルがEVENからAUTOに変わるのでご注意ください。

この新しく追加された分散スタイルAUTOは、テーブルのレコード数が少ない間は分散スタイルALLとして動作しますが、レコード数が増加すると自動的に分散スタイルEVENに切り替わります。

分散スタイルAUTOの動作

分散スタイルがAUTOの場合、レコード数が少ないうちは全てのコンピュートノードに同じデータを配置する分散スタイルALLとして動作しますが、レコード数がしきい値を超えると自動的にラウンドロビンで均等にデータを配置する分散スタイルEVENに切り替わります。全てのコンピュートノードに同じデータを配置する分散スタイルALLは、テーブル間の結合が常にコンピュートノード内で済むことメリットがありますが、一方でレコード数が多くなるとディスクの空間効率やコピーのオーバヘッドが大きくるというデメリットが生じるため、レコード数がしきい値を超えるとラウンドロビンで均等に配置EVENに自動的に切り替えると考えられます。

RedshiftのテーブルのDISTSTYLEにAUTOが追加され、東京リージョンでも使えるようになりました。今まではデフォルトは分散スタイルEVENだったのですが、これからはデフォルトではじめはALL、件数が増えてくるとEVENというようにダイナミックに持ち方が変わる動きになります。

下記の例では、dist_autoテーブルは明示的に分散スタイルAUTO、dist_auto_defaultテーブルは分散スタイルを指定していませんが分散スタイルAUTOに設定されています。一番下のテーブル一覧では、ともにレコード数が1レコードと少ないため、分散スタイルがAUTO(ALL)と表示されています。

cmdb=# create table dist_key (col1 int) diststyle key distkey (col1);
CREATE TABLE
cmdb=# create table dist_even (col1 int) diststyle even;
CREATE TABLE
cmdb=# create table dist_all (col1 int) diststyle all;
CREATE TABLE
cmdb=# create table dist_auto (col1 int) diststyle auto;
CREATE TABLE
cmdb=# create table dist_auto_default (col1 int);
CREATE TABLE

cmdb=# insert into dist_key(col1) values(1);
INSERT 0 1
cmdb=# insert into dist_even(col1) values(1);
INSERT 0 1
cmdb=# insert into dist_all(col1) values(1);
INSERT 0 1
cmdb=# insert into dist_auto(col1) values(1);
INSERT 0 1
cmdb=# insert into dist_auto_default(col1) values(1);
INSERT 0 1

cmdb=# select "schema", "table", diststyle from svv_table_info where "table" like 'dist%';
schema | table | diststyle
--------+-------------------+-----------
public | dist_key | KEY(col1)
public | dist_all | ALL
public | dist_auto | AUTO(ALL)
public | dist_auto_default | AUTO(ALL)
public | dist_even | EVEN
(5 rows)

分散スタイルの自動変更を確認

分散スタイルAUTOのテーブルを新規作成して、実際にデータを格納して確認しました。

cmdb=# DROP TABLE "public"."lineorder";
DROP TABLE
cmdb=# CREATE TABLE IF NOT EXISTS "public"."lineorder"
cmdb-# (
cmdb(# "lo_orderkey" INTEGER ENCODE raw
cmdb(# ,"lo_linenumber" INTEGER ENCODE raw
cmdb(# ,"lo_custkey" INTEGER ENCODE raw
cmdb(# ,"lo_partkey" INTEGER ENCODE raw
cmdb(# ,"lo_suppkey" INTEGER ENCODE raw
cmdb(# ,"lo_orderdate" INTEGER ENCODE raw
cmdb(# ,"lo_orderpriority" VARCHAR(15) ENCODE lzo
cmdb(# ,"lo_shippriority" VARCHAR(1) ENCODE lzo
cmdb(# ,"lo_quantity" INTEGER ENCODE lzo
cmdb(# ,"lo_extendedprice" INTEGER ENCODE lzo
cmdb(# ,"lo_ordertotalprice" INTEGER ENCODE lzo
cmdb(# ,"lo_discount" INTEGER ENCODE lzo
cmdb(# ,"lo_revenue" INTEGER ENCODE lzo
cmdb(# ,"lo_supplycost" INTEGER ENCODE lzo
cmdb(# ,"lo_tax" INTEGER ENCODE lzo
cmdb(# ,"lo_commitdate" INTEGER ENCODE lzo
cmdb(# ,"lo_shipmode" VARCHAR(10) ENCODE lzo
cmdb(# )
cmdb-# DISTSTYLE AUTO
cmdb-# ;
CREATE TABLE

最初は1行インサートします。分散スタイルはAUTO(ALL)です。

cmdb=# -- 1行インサート
cmdb=# insert into "public"."lineorder" (lo_orderkey,lo_linenumber,lo_custkey,lo_partkey,lo_suppkey,lo_orderdate) values(1,2,3,4,5,6);
INSERT 0 1
cmdb=# select "schema", "table", diststyle from svv_table_info where "schema" = 'public' and "table" = 'lineorder';
schema | table | diststyle
--------+-----------+-----------
public | lineorder | AUTO(ALL)
(1 row)

最初は10行インサートします。分散スタイルはAUTO(ALL)のまま変わりません。

cmdb=# -- 10行インサート
cmdb=# insert into "public"."lineorder" (lo_orderkey,lo_linenumber,lo_custkey,lo_partkey,lo_suppkey,lo_orderdate) values
cmdb-# (1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6),(1,2,3,4,5,6);
INSERT 0 10
cmdb=# select "schema", "table", diststyle from svv_table_info where "schema" = 'public' and "table" = 'lineorder';
schema | table | diststyle
--------+-----------+-----------
public | lineorder | AUTO(ALL)
(1 row)

次に1行のみディープコピー(INSERT INTO ... SELECT)します。するとレコード数は12レコードしかありませんが分散スタイルはAUTO(EVEN)に変更されました。なお、一度AUTO(EVEN)に変更するとレコードを削除しても分散スタイルがAUTO(ALL)に戻ることはありません。

cmdb=# -- 1行のみディープコピー
cmdb=# insert into "public"."lineorder" select * from sady_lineorder limit 1;
INSERT 0 1
cmdb=# select "schema", "table", diststyle from svv_table_info where "schema" = 'public' and "table" = 'lineorder';
schema | table | diststyle
--------+-----------+------------
public | lineorder | AUTO(EVEN)
(1 row)

本当は、500万レコード未満でAUTO(ALL)からAUTO(EVEN)に切り替わる境界値を探して確認したかったのですが、INSERT INTOを数万回叩き続ける元気がないので諦めました。

最後に

今回の検証で具体的にAUTO(ALL)からAUTO(EVEN)に切り替わる境界値を探して確認したかったのですが、INSERT INTOを数万回叩き続ける元気がないので諦めました。

以下の公開情報に

DISTSTYLE AUTO is a great go-to for all tables < ~5 million rows.

という解説があり、500万行がしきい値ではないかと推測しています。少なくとも分散スタイルAUTOは500万行を超えるテーブルには不向きであることは確かなようです。

Redshiftの分散キーに不慣れな利用者が一時的に作成するテーブルに分散スタイルAUTOはレコード数に応じてパフォーマンスが改善するので便利ではないかと考えられます。

私はレコード数の変動でパフォーマンスが大きく変わるような設計はしたくないので、プロダクション環境においては、積極的に分散スタイルAUTOを選択することはおすすめしません。