ここ数年、Pythonが統計・機械学習界隈で人気を高めています。PostgreSQLやその商用版であるEDB Postgres Advanced Server(EPAS)にはDB内部で動作するプロシージャをPythonで作成することができるPL/Pythonというモジュールがサポートされています。PL/Pythonは使用するPythonのバージョンにあわせて、Python2系をサポートするPL/PythonとPython3系をサポートするPL/Python3があります。
EPASではデフォルトでPython3用のPL/Python3がバンドルされていますが、使用するまでにはいくつか注意点があるので、セットアップ手順といくつかのTipsをご紹介します。
環境
本手順は以下環境で実施しています。
* OS: OracleLinux 6.4 64bit
* DB: EPAS 9.6.2 (64bit)
Python3のセットアップ
Python3が利用できない環境でPL/Python3をインストールしようとすると以下の様なエラーが発生します。
[root@yamax as9.6]# edb-psql edb enterprisedb -c "create extension plpython3u;"
ERROR: ライブラリ"/opt/edb/as9.6/lib/plpython3.so"をロードできませんでした: libpython3.3m.so.1.0: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません
これは、plpython3のライブラリがPython3の共有オブジェクトである
libpython3.3m.so.1.0が参照できないために発生しています。OracleLinuxやCentOS等のRedhat系のLinuxでは最新の7.x系であってもPython2.xのみがデフォルトではインストールされています。EPAS-9.6にバンドルされているPL/Python3はPython3.3を必要としています。そのため、別途Python3をセットアップする必要があります。
※次のEPAS-10ではPython3.4に対応したPL/Python3がバンドルされる予定です。
Python3系はRedhat等の公式リポジトリには2017年6月現在利用可能なバイナリは公開されておらず、yumでの導入には外部のリポジトリを追加する必要があります。そこで今回はPython3.3もソースからインストールします。
Python3のソースのダウンロードPython3のソースのダウンロード
2017年6月現在、Pythonは3.3系の最新はPython3.3.6です。以下のURLよりソースを入手できます。
入手したtarballをEDB-Postgresを導入しているサーバ上に配置し、以下の手順でコンパイル・インストールします。今回は、Python3を
/opt/pythonというディレクトリを指定して導入します。このあたりの手順は、
ソースファイルからPostgreSQLをインストールする手順
と殆ど同じです。
[root@yamax ~]# mkdir /opt/python
[root@yamax ~]# chmod 777 /opt/python
[root@yamax ~]# cd Python3.3.6ソース展開先
[root@yamax Python-3.3.6]# ./configure --enable-shared --prefix=/opt/python/
[root@yamax Python-3.3.6]# make && make install
configure時の--enable-sharedにより、Pythonの共有ライブラリを作成するように指定しています。これを指定しない場合、PL/Python3が必要とする共有ライブラリが作成されないため注意します。これで/opt/python/bin/python3としてPython3がインストールされます。また、libpython3.3m.so.1.0は/opt/python/lib配下に配置されます。
LD_LIBRARY_PATHの編集
PL/Python3を使用するには、libpython3.3m.so.1.0が配置されている/opt/python/libを参照するようにEPASの環境変数を指定する必要があります。具体的には、EPAS起動時のLD_LIBRARY_PATH環境変数に/opt/python/libを追加します。EPASは/etc/init.d/配下のスクリプトから起動されます。9.6の場合は/etc/init.d/edb-as-9.6です。
本スクリプトをvi等で以下のように編集します。
修正前
714 export LD_LIBRARY_PATH=$INSTALLDIR/lib:$LD_LIBRARY_PATH_PL_LANGUAGES:$LD_LIBRARY_PATH
715 export DATADIR="/opt/edb/as9.6/data"
716 export SERVICE_CONF_FILE=""
修正後
714 export LD_LIBRARY_PATH=$INSTALLDIR/lib:$LD_LIBRARY_PATH_PL_LANGUAGES:$LD_LIBRARY_PATH:/opt/python/lib # この行を編集
715 export DATADIR="/opt/edb/as9.6/data"
716 export SERVICE_CONF_FILE=""
編集後、EPASを再起動することでLD_LIBRARY_PATHに/opt/python/libが追加された状態で起動します。
[root@yamax ~]# service edb-as-9.6 restart
PL/Python3のインストール
PL/Python3は各データベースでcreate extension plpython3uを実行して導入します。
[root@yamax as9.6]# edb-psql edb enterprisedb -c "create extension plpython3u;"
エラーがでなければ作成完了です。実際にログインしてPL/Python3を使用してみます。以下はEPASのドキュメントにあるPL/Pythonで2つの引数の値のうち大きい方を戻すサンプル関数です。
edb=# CREATE FUNCTION pymax (a integer, b integer)
edb-# RETURNS integer
edb-# AS $$
edb$# if a > b:
edb$# return a
edb$# return b
edb$# $$ LANGUAGE plpython3u;
CREATE FUNCTION
edb=# select pymax(1,10);
pymax
-------
10
(1 行)
Python3で作成したコードが正しく実行できており、無事にPL/Pythono3が導入できていることが確認できました。
PL/Python3内でSQLの実行
PL/Python3で作成した関数内でSQLを実行する場合は
plpyモジュール
を使用します。一般的に使用され得るバインド値を用いたSQLを実行するサンプルをご紹介します。
以下は引数としてDEPTNOを取り、EMP表の中でそのDEPTNOに該当する行数を戻す関数です。count(*)を使うほうが早いですが、plpyモジュールの例として、PL/Python3内で行数を数えています。
edb=# create or replace function check_emp_count(v_deptno int)
edb-# RETURNS int
edb-# AS $$
edb$# # 行数カウント変数
edb$# row_count = 0
edb$# # deptnoをバインド変数としてSQLをprepare
edb$# # バインド変数の型はintであることを明示
edb$# plan = plpy.prepare("select 'x' from emp where deptno=$1", ["int"])
edb$# # バンド変数に関数の引数として受けたv_deptnoを設定し実行
edb$# # 1行ずつfor文で処理される
edb$# for row in plpy.cursor(plan, [v_deptno]):
edb$# row_count += 1
edb$# return row_count
edb$# $$ LANGUAGE plpython3u;
CREATE FUNCTION
edb=# select check_emp_count(10);
check_emp_count
-----------------
3
(1 行)
実際にEMP表でDEPTNO=10の行数を確認した結果とも致しています。
edb=# select count(*) from emp where deptno=10;
count
-------
3
(1 行)
まとめ
EPAS上でPL/Python3を使用するまでの流れと簡単な使用例をご紹介しました。まだまだ利用例は少ないですが、今後EPAS上でPL/Python3の構築を検討される際の一助になれば幸いです。