Redshift ストレージの空き容量を増やすなら、SVV_TABLE_INFOシステムビューを見るのが効果的


前回の[Redshiftのストレージ容量のメンテナンス](https://qiita.com/imaiworks/items/f476ae9cd5187d060d45)で取りあげたSVV_TABLE_INFOシステムビュー。
このビューにencodedというフィールドがあるのですが
所どころ「N」なってたりすることがあります。

```sql:Redshift
rsdb1=# select * from SVV_TABLE_INFO;

 database | schema | table_id |  table  | encoded | diststyle | sortkey1 | max_varchar | sortkey1_enc | sortkey_num | size | pct_used | empty | unsorted | stats_off | tbl_rows  | skew_sortkey1 | skew_rows 
----------+--------+----------+---------+---------+-----------+----------+-------------+--------------+-------------+------+----------+-------+----------+-----------+-----------+---------------+-----------
 rsdb1    | public |   100523 | table2  | Y       | EVEN      |          |        4096 |              |           0 |  190 |   0.0498 |     0 |          |     11.34 |    932239 |               |          
 rsdb1    | public |   100617 | table3  | Y       | EVEN      |          |        4096 |              |           0 |  591 |   0.1549 |     0 |          |      8.96 |   8566046 |               |          
 rsdb1    | public |   100747 | table4  | N       | EVEN      |          |        4096 |              |           0 | 8049 |   0.0466 |     0 |          |      0.00 |    130690 |               |          
 rsdb1    | public |   150278 | table5  | Y       | EVEN      |          |       65535 |              |           0 |  178 |   2.1103 |     0 |          |     17.82 | 132678814 |               |          
 rsdb1    | public |   159527 | table6  | Y       | EVEN      |          |         512 |              |           0 |  692 |   0.1814 |     0 |          |      4.10 |     62850 |               |          
 rsdb1    | public |   100565 | table7  | N       | EVEN      |          |        4096 |              |           0 | 7527 |   1.9734 |     0 |          |      5.15 |  12146431 |               |          
``` 
       
encodedが意味しているところは、
「該当のテーブルのすべてのフィールド/列が非圧縮です」
ということ。

Redshiftは列圧縮機能が搭載されており、列ごとに任意に列圧縮モードが指定できます。
実際にはどのような列圧縮かを調べるには
各列ごとの定義状況が確認できるpg_table_defシステムカタログを参照するとよいです。

```sql:Redshift
rsdb1=# SELECT * FROM pg_table_def WHERE tablename = 'table4';

 schemaname | tablename | column      |          type           | encoding | distkey | sortkey | notnull 
------------+-------------------------+---------------------------------+-------------------------+----------+---------+---------+---------
 public     | table4    | customerid  | character varying(20)   | none     | f       |       0 | f
 public     | table4    | label       | character varying(100)  | none     | f       |       0 | f
 public     | table4    | impressions | bigint                  | none     | f       |       0 | f
 public     | table4    | grpid       | bigint                  | none     | f       |       0 | f
 public     | table4    | grpname     | character varying(256)  | none     | f       |       0 | f
 public     | table4    | status      | character varying(256)  | none     | f       |       0 | f
 public     | table4    | type1       | character varying(256)  | none     | f       |       0 | f
```
encodingが列圧縮のモードです。
すべて「none」と散々な状態・・orz

列圧縮のモードは以下を参照してみて下さい。
[AWS Documentation » Amazon Redshift » データベース開発者ガイド » テーブルの設計 » 列圧縮タイプの選択 » 圧縮エンコード
](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c_Compression_encodings.html)

列圧縮のモードはCreateTable文で指定できます
例えば

```sql:Redshift
create table testtable1
(
  id int,
  text varchar(256) encode LZO
);
``` 

と指定すれば良い感じです。
指定しなくてもRedshiftがよしなに列圧縮モードを設定してくれるようですが
聞いた話では、COPYコマンドで流し込みを行ったときに自動で列圧縮モード指定が行われるが
insert文で1行1行インサートして入れた際はraw (非圧縮) になってしまうそうです。

列圧縮と聞くと、展開するときにCPUパワー使うから使いたくないという方もいるかと思いますが
その筋に方々は圧縮展開のCPUコストよりストレージからの読み込みバイト数によるIOコストのほうが格段に大きいので
列圧縮は大量データの高速化には最適という話も聞きます。
OLTPであれば少量のデータの読み書きが大量に発生しますが、
DWHでは書き込みはLOADで行い、それらのデータはたまにしか使わず、使う時は読み込みが大量！！・・
という使い方ですのでストレージの料金的なコストのほうを優先にしてもいいと思います。


ということで、encodedがNな非圧縮列ばかりのテーブルを見つけたら

１．同一内容の別名テーブルを用意(圧縮方法はしていしなくてもよい)
２．```insert into 同一内容の別名テーブル名 select * from 元テーブル名``` でさくっと内容を移す
３．一応count(*)をとったりsum()などの集計関数で値をもとめ内容が同じかを確認
４．元テーブルを削除、alter文で別名テーブル名のテーブル名を変更

と行うだけで感覚的にはテーブル容量が半分から３割程度に削減できます。