実行環境
仮想マシンを、VirtualBoxのウィンドウ非表示モード(Headless)で起動し、インストール&クエリをホスト側Windowsのコンソールで行いました。
直接関係ありませんがゲスト-ホスト間のネットワークはNAT + ポートフォワーディングで行い、二つ目の画像のようにホスト側の5436番ポートをゲスト側5432に転送。これでホスト側のlocalhost:5436へのリクエストがゲスト側のPostgreSQLにつながります。(自分の備忘録をかねてメモ)。
yumでインストール
yumでPL/v8のパッケージを探すとPostgreSQL 9.3用が既にあり、これをインストールするだけ。終わったらPostgreSQLを再起動します(必須かどうか分かりませんが、念のためを兼ねて)。
yum list | grep plv8
plv8_93.x86_64 1.4.1-1.rhel6 pgdg93
plv8_93-debuginfo.x86_64 1.4.1-1.rhel6 pgdg93
# yum -y install plv8_93
# service postgresql-9.3 restart
次はWindowsの時と全く同じ。テスト用データベース作成、そのDBへ接続、CREATE EXTENSIONでインストール、PL/v8のバージョン確認(1.4.1だった)。
CREATE DATABASE plv8_test
TEMPLATE = template0
LC_COLLATE = 'C'
LC_CTYPE = 'C';
# \c plv8_test
CREATE EXTENSION plv8;
SELECT extname, extversion FROM pg_extension;
extname | extversion
---------+------------
plpgsql | 1.0
plv8 | 1.4.1
テスト(Typed array)
昨日初めて試したPL/v8のTyped arrayを、今回も少しテスト。INT4配列を合計する昨日と同じストアドと、比較用に、配列でなくスカラを一つずつ足す集約関数を作ります。
CREATE OR REPLACE FUNCTION int4ary_sum
(ary plv8_int4array)
RETURNS int8 LANGUAGE plv8 IMMUTABLE STRICT AS $$
var sum = 0;
for (var i = ary.length - 1; 0 <= i; i--) {
sum += ary[i];
}
return sum;
$$;
CREATE OR REPLACE FUNCTION int4rows_sum_sfunc
(sum int8, val int4)
RETURNS int8 LANGUAGE plv8 IMMUTABLE STRICT AS $$
return sum + val;
$$;
CREATE AGGREGATE int4rows_sum (int4) (
sfunc = int4rows_sum_sfunc,
stype = int8,
initcond = 0
);
次に、テスト用テーブルを二つ作成。片方は普通に100万行のINT4型、もう一つは配列1レコードにまとめたもの。前者には集約関数を使って合計を出し、後者にはPL/v8のTyped arrayによるストアドを使い、それぞれの処理時間をざっくり見てみます。
CREATE TABLE tb_example_rows AS
SELECT generate_series(1, n) AS val
FROM cast(pow(10, 6) AS int) AS n;
CREATE TABLE tb_example_ary AS
SELECT array_agg(gs) AS ary
FROM cast(pow(10, 6) AS int) AS n,
generate_series(1, n) AS gs;
SELECT array_length(ary, 1)
FROM tb_example_ary;
array_length
--------------
1000000
(1 行)
今日は実行1回のみ、かつクエリ全体の所要時間しか見ないので大雑把ですが、とりあえずの結果。↓ 100万行のテーブルに組み込みの集約関数(sum)を使うと約100ミリ秒、単純にスカラを足すPL/v8のストアドによる集約関数は約600ミリ秒、昨日と同じPL/v8のTyped array利用だと13ミリ秒と最も高速。最後のは、一つ一つの値を配列にまとめる時間が事前にかかってるのを考慮する必要があります。
SELECT sum(val)
FROM tb_example_rows;
sum
--------------
500000500000
(1 行)
時間: 98.672 ms
SELECT int4rows_sum(val)
FROM tb_example_rows;
(1 行)
時間: 612.027 ms
SELECT int4ary_sum(ary)
FROM tb_example_ary;
(1 行)
時間: 13.554 ms
データが配列になっていればPL/v8ストアドが最良(速度的にも取り扱い的にも)な感じですが、普通のテーブルを対象に独自の集約をする場合は、引き続き検討します。配列化にかかる時間を入れてもTyped arrayの方が速いなら、それが一番。行数や処理内容によっても変わると思うけど。
今日で、PostgreSQL 9.5以外にはPL/v8を入れました。9.5 AlphaでPL/v8を使う例はざっとウェブ検索しても見当らないので、自力で何とかできなければ「インストールまとめ」は今日で終わります。追記(9月26日)9.5 Alphaでもインストールできたため、続きがあります。