Amazon Redshiftで列圧縮エンコーディングをALTER TABLEコマンドで変更してみた

2020.10.24

先日、Amazon Redshiftで列圧縮エンコーディングの変更がALTER TABLEコマンドで実行できるようになったので試してみました!

嬉しいポイント

既存のテーブルに対して列圧縮エンコーディングを変更する場合は、下記の手間がありました。

  • 新規で列圧縮エンコーディングを定義済みのテーブルを作成、既存テーブルのデータ移行が必要
  • 実際の本番環境で稼働しているRedshiftクラスタなどの場合は、念のために事前にスナップショットを取得する
  • 列圧縮エンコーディングを変更したい対象カラムが1つの場合でも、テーブルを再作成しないといけない

今回のアップデートにより、上記を考慮する必要なくALTER TABLE [対象テーブル名] ALTER COLUMN [対象カラム名] ENCODE [変更したい列圧縮エンコーディング名]コマンドで列圧縮エンコーディングが変更できるようになりました。

動作環境

  • クライアント:psql 12.3
  • Redshiftクラスター(ノード:dc2.large、ノード数:1):1.0.20091 ※1.0.19506以降のバージョンで確認可能

サンプルデータ

下記のとおり、テーブル作成・ロードして検証していきます、

dev=# CREATE SCHEMA sample;
CREATE SCHEMA
dev=#
dev=# CREATE TABLE sample.lineorder
dev-# (
dev(#   lo_orderkey          INTEGER NOT NULL ENCODE ZSTD,
dev(#   lo_linenumber        INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_custkey           INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_partkey           INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_suppkey           INTEGER NOT NULL ENCODE ZSTD,
dev(#   lo_orderdate         INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_orderpriority     VARCHAR(15) NOT NULL ENCODE LZO,
dev(#   lo_shippriority      VARCHAR(1) NOT NULL ENCODE ZSTD,
dev(#   lo_quantity          INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_extendedprice     INTEGER NOT NULL ENCODE ZSTD,
dev(#   lo_ordertotalprice   INTEGER NOT NULL ENCODE ZSTD,
dev(#   lo_discount          INTEGER NOT NULL ENCODE ZSTD,
dev(#   lo_revenue           INTEGER NOT NULL ENCODE ZSTD,
dev(#   lo_supplycost        INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_tax               INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_commitdate        INTEGER NOT NULL ENCODE AZ64,
dev(#   lo_shipmode          VARCHAR(10) NOT NULL ENCODE ZSTD
dev(# );
dev(#
dev(# copy sample.lineorder from 's3://awssampledbuswest2/ssbgz/lineorder'
dev(# iam_role 'arn:aws:iam::XXXXXXXXXXXX:role/TestRole'
dev(# gzip region 'us-west-2';
dev(#
dev=# select count(*) from sample.lineorder;
   count
-----------
 600037902
(1 row)

dev=#

列圧縮エンコーディングの変更

ANALYZE COMPRESSIONコマンドを実行し、最適な列圧縮エンコーディング、その列圧縮エンコーディングに変更した場合の推定減少パーセントを確認します

dev=# analyze compression sample.lineorder;
   Table   |       Column       | Encoding | Est_reduction_pct
-----------+--------------------+----------+-------------------
 lineorder | lo_orderkey        | delta32k | 21.48
 lineorder | lo_linenumber      | az64     | 0.00
 lineorder | lo_custkey         | az64     | 0.00
 lineorder | lo_partkey         | az64     | 0.00
 lineorder | lo_suppkey         | az64     | 16.38
 lineorder | lo_orderdate       | az64     | 0.00
 lineorder | lo_orderpriority   | bytedict | 60.65
 lineorder | lo_shippriority    | zstd     | 0.00
 lineorder | lo_quantity        | az64     | 0.00
 lineorder | lo_extendedprice   | zstd     | 0.00
 lineorder | lo_ordertotalprice | zstd     | 0.00
 lineorder | lo_discount        | az64     | 17.79
 lineorder | lo_revenue         | zstd     | 0.00
 lineorder | lo_supplycost      | az64     | 0.00
 lineorder | lo_tax             | az64     | 0.00
 lineorder | lo_commitdate      | az64     | 0.00
 lineorder | lo_shipmode        | bytedict | 19.14
(17 rows)
dev=#

テーブルデータのストレージ使用量(単位:MB)も確認しておきます

dev=# select name as tbl_name, cnt as size from
dev-# (
dev(#   select tbl, count(*) as cnt
dev(#   from stv_blocklist
dev(#   where tbl in (
dev(#   select id
dev(#   from stv_tbl_perm)
dev(#   group by tbl
dev(# ) block_list
dev-# inner join stv_tbl_perm
dev-# on block_list.tbl=stv_tbl_perm.id
dev-# group by tbl, stv_tbl_perm.name, block_list.cnt
dev-# order by cnt;
   tbl_name                        | size
-----------------------------------+------
 lineorder                         | 24816
(1 row)
dev=#

推定減少パーセントが一番高いlo_orderpriorityカラムの列圧縮エンコーディングを変更してみます。

dev=# alter table sample.lineorder alter column lo_orderpriority encode bytedict;
ALTER TABLE
dev=#
dev=# select "column", type, encoding from pg_table_def where tablename = 'lineorder' and "column" = 'lo_orderpriority';
      column      |         type          | encoding
------------------+-----------------------+----------
 lo_orderpriority | character varying(15) | bytedict
(1 row)

dev=#

列圧縮エンコーディングを期待通り変更できました!

dev=# select name as tbl_name, cnt as size from
dev-# (
dev(#   select tbl, count(*) as cnt
dev(#   from stv_blocklist
dev(#   where tbl in (
dev(#   select id
dev(#   from stv_tbl_perm)
dev(#   group by tbl
dev(# ) block_list
dev-# inner join stv_tbl_perm
dev-# on block_list.tbl=stv_tbl_perm.id
dev-# group by tbl, stv_tbl_perm.name, block_list.cnt
dev-# order by cnt;
   tbl_name                        | size
-----------------------------------+------
 lineorder                         | 23862

テーブルデータのストレージ使用量(単位:MB)が減少していることも確認できました。

注意点

ALTER TABLEコマンドで列圧縮エンコーディングを変更する場合は、下記注意が必要です。

You can't alter a column to the same encoding as currently defined for the column.

既に対象カラムに設定されている列圧縮エンコーディングを指定するとエラーになります。

dev=# alter table sample.lineorder alter column lo_shippriority encode zstd;
ERROR:  ALTER COLUMN ENCODE does not support changing to same encode type: zstd
dev=#

You can't alter the encoding for a column in a table with an interleaved sortkey.

interleaved sortkeyで指定されているカラムの列圧縮エンコーディングを変更しようとするとエラーになります。

dev=# alter table sample.test alter column cust_id encode zstd;
ERROR:  Unsupported ALTER TABLE ALTER COLUMN ENCODE on table with interleaved sortkey.
dev=#

おわりに

下記ブログにてテーブルを再作成して列圧縮エンコーディングの変更をする方法を書いたのですが、今回試したALTER TABLEコマンドでの変更が楽だったので個人的には非常にありがたいアップデートでした!
これからは気軽に列圧縮エンコーディングの変更ができそうですね!

どなたかの参考になれば幸いです。以上、DA(データアナリティクス)事業本部のナガマサでした。

参考