PostgreSQL、 Apache Arrowフォーマットのファイル読めるってよ！


# はじめに
本日はPostgreSQL＋分析処理という観点で、HeteroDB社の海外さんが作成されているPG-Stromに同梱されているArrow_FDW（列指向データストア）について、ご紹介します。

Arrow_FDWとは、Apache ArrowフォーマットのファイルをPostgreSQL上からテーブルとして扱うことができる外部モジュールです。PG-Stromでの処理性能を高めるため、作成されており、PG-Stromと併せて使用することで大量データも高速で処理することができます。

詳細はPG-Stromの[マニュアル](https://heterodb.github.io/pg-strom/ja/arrow_fdw/)をご参照ください。

この記事では、実際にArrow_FDWを使って、PostgreSQLからpythonで作成したArrowファイルを参照できるかというのを試してみようと思います。

# インストール手順
## PostgreSQL
ちょっと古い記事ですが、導入手順は基本的に何も変わらないので、バージョンの部分を変更して使ってください。
[参考：PostgreSQLのインストール手順](https://qiita.com/U_ikki/items/21242bc6497ed12e82e7)

※Arrow_FDWはPostgreSQL11以上でしか対応していないので要注意。

## Arrow_FDW

Arrow_FDWはPG-Stromをインストールし、有効化することで利用できます。
（***単体は提供されていないので、PG-StromがサポートするGPUを乗せた環境が必要となります。***）

インストール手順はマニュアル（https://heterodb.github.io/pg-strom/ja/install ）を参考にしつつ実施する。

```bash
# dkms, pcsc-lite-libsのインストール (事前にepelのリポジトリを登録しておくこと)
sudo yum --enablerepo=epel install pcsc-lite-libs
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/pcsc-lite-libs-1.8.8-8.el7.x86_64.rpm
rpm -ivh pcsc-lite-libs-1.8.8-8.el7.x86_64.rpm

# cudaのインストール（PG-Stromで要求されるため入れておく）
# https://developer.nvidia.com/cuda-toolkit で環境情報を入れていくと必要なコマンドが表示されるのでそれを実行する
sudo yum-config-manager --add-repo http://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo
sudo yum clean all
sudo yum -y install nvidia-driver-latest-dkms cuda

# PG-Stromのインストール
sudo yum install https://heterodb.github.io/swdc/yum/rhel7-x86_64/heterodb-swdc-1.0-1.el7.noarch.rpm
sudo yum install pg_strom-PG11
```

# 確認結果

## PG-Strom有効化
パッケージさえ入れてしまえば、あとはPostgreSQL上で有効化して使うだけです。
PostgreSQLの設定ファイルを変更して、再起動すればOKです。

```bash
# PG-Stromを有効化する
echo "shared_preload_libraries = 'pg_strom'" >> $PGDATA/postgresql.conf
```

有効化後はPostgreSQLにアクセスし、pgstromをEXTENSIONに登録します。

```sql
CREATE EXTENSION pg_strom;
```

CREATE EXTENSIONすると自動で以下の内容でArrow_FDWの定義も行われるので、利用者は`CREATE FOREIGN TABLE`だけでArrow_FDWを利用することができます。

```sql
-- 以下の内容は自動で実行されるArrow_FDWの定義内容です。
CREATE SCHEMA IF NOT EXISTS pgstrom;

CREATE FUNCTION pgstrom.arrow_fdw_handler()
  RETURNS fdw_handler
  AS '$libdir/pg_strom','pgstrom_arrow_fdw_handler'
  LANGUAGE C STRICT;

CREATE FUNCTION pgstrom.arrow_fdw_validator(text[],oid)
  RETURNS void
  AS '$libdir/pg_strom','pgstrom_arrow_fdw_validator'
  LANGUAGE C STRICT;

CREATE FOREIGN DATA WRAPPER arrow_fdw
  HANDLER   pgstrom.arrow_fdw_handler
  VALIDATOR pgstrom.arrow_fdw_validator;

CREATE SERVER arrow_fdw
  FOREIGN DATA WRAPPER arrow_fdw;
```


## Arrowファイルの作成
Apache Arrowフォーマットのファイルの作成方法は色々とあります。
試すだけであれば、PG-Stromに同梱されているpg2arrowというユーティリティツールを使用するのが一番楽だと思いますのでお勧めです。現在のテーブルをArrowファイルとしてダンプすることができます。
※[@nuko_yokohamaさんの記事](https://qiita.com/nuko_yokohama/items/b5fe90834300a6747eef)に、実際にpg2arrowを試した情報が載っているのでご参考ください。
　
と、まぁ便利なものはあるんですが、今回はせっかくなので、各言語で共通フォーマットで使えるArrowフォーマットということなので、別途python（pandasのDataFrame）で作成しておいたArrowファイルをPostgreSQLから直接利用できるよ！というところを試してみます。

Arrowファイルの作成は以下のコードで行います。

```genArrowFile.py
import pandas as pd
import pyarrow as pa

df = pd.DataFrame({"a": [1,2,3],
                   "b": ["hello", "arrow_fdw", "world!"]}, dtype=unicode)
record_batch = pa.RecordBatch.from_pandas(df)

with pa.OSFile("/tmp/pandas.arrow", "wb") as sink:
    schema = record_batch.schema
    writer = pa.RecordBatchFileWriter(sink, schema)
    writer.write_batch(record_batch)
    writer.close()
```
※こちらは　[クリアコード社の須藤さん](https://www.slideshare.net/kou/datasciencerb) のスライドの内容を利用させていただきました。

コードを実行すると以下にArrowファイルが作成されたことを確認できます。

```bash
$ python genArrowFile.py
$ ls /tmp/pandas.arrow 
/tmp/pandas.arrow
```

## PostgreSQLからArrowファイルにアクセスする
では、最後にPostgreSQLからArrowファイルにアクセスしてみます。

外部テーブルを定義する際、Arrow_Fdwでは`IMPORT FOREIGN SCHEMA`構文を用いた作成に対応しているので、Arrowファイルのデータ型に合わせて自動でテーブル定義を生成することができます。
（データ型等、ミスマッチになってしまうとエラー等発生するため、可能な限り自動生成したほうが安全と言えます。）

IMPORTし、追加されたテーブル（Arrowファイル）に対して、SELECTを実行した結果が以下のとおりです。

```
postgres=# IMPORT FOREIGN SCHEMA pandas_tbl FROM SERVER arrow_fdw INTO public OPTIONS (file '/tmp/pandas.arrow');
IMPORT FOREIGN SCHEMA
postgres=# \d pandas_tbl 
              Foreign table "public.pandas_tbl"
 Column | Type | Collation | Nullable | Default | FDW options 
--------+------+-----------+----------+---------+-------------
 a      | text |           |          |         | 
 b      | text |           |          |         | 
Server: arrow_fdw
FDW options: (file '/tmp/pandas.arrow')

postgres=# select * from pandas_tbl ;
 a |     b     
---+-----------
 1 | hello
 2 | arrow_fdw
 3 | world!
(3 rows)
```

pythonで書いていたデータがちゃんとPostgreSQL側から参照できていることを確認できました。
良い感じですね。

# さいごに
今回、pythonで作成したApache Arrowフォーマットのファイルに対して、PostgreSQLからアクセスしてデータを参照できることを確認しました。
今後、分析系で引っかかるような仕事があれば、ぜひ使ってみたいな～。