象と戯れ

 | 

2009-09-30

PL/JavaScript => plv8

23:46 | PL/JavaScript => plv8 - 象と戯れ を含むブックマーク はてなブックマーク - PL/JavaScript => plv8 - 象と戯れ

仕事そっちのけでplv8(pl/javascript)。

regression=# CREATE OR REPLACE FUNCTION plv8_test(keys text[], vals text[]) RETURNS text AS $$
var o = {};
for(var i=0; i<keys.length; i++){
  o[keys[i]] = vals[i];
}
return JSON.stringify(o);
$$ LANGUAGE plv8 IMMUTABLE STRICT;
CREATE FUNCTION

regression=# SELECT plv8_test(ARRAY['name', 'age'], ARRAY['Tom', '29']);
         plv8_test         
---------------------------
 {"name":"Tom","age":"29"}
(1 row)

というところまで動くようになった。

パフォーマンスは、関数内の処理にもよるけど、呼出オーバーヘッド的にはplpgsqlよりちょっといいぐらい。plperlは使ったことがないけど、それと同じぐらいかな??

regression=# CREATE OR REPLACE FUNCTION plpgsql_add(a int, b int) RETURNS int AS $$ BEGIN RETURN a + b; END; $$ LANGUAGE plpgsql;
CREATE FUNCTION

regression=# CREATE OR REPLACE FUNCTION plv8_add(a int, b int) RETURNS int AS $$ return a + b; $$ LANGUAGE plv8;
CREATE FUNCTION

regression=# EXPLAIN ANALYZE SELECT plpgsql_add(unique1, unique2) FROM tenk1;
                                                QUERY PLAN                      
                           
--------------------------------------------------------------------------------
---------------------------
 Seq Scan on tenk1  (cost=0.00..2945.00 rows=10000 width=8) (actual time=0.280..
60.883 rows=10000 loops=1)
 Total runtime: 83.532 ms
(2 rows)

regression=# EXPLAIN ANALYZE SELECT plv8_add(unique1, unique2) FROM tenk1;
                                                QUERY PLAN                      
                           
--------------------------------------------------------------------------------
---------------------------
 Seq Scan on tenk1  (cost=0.00..2945.00 rows=10000 width=8) (actual time=0.334..
40.906 rows=10000 loops=1)
 Total runtime: 70.803 ms
(2 rows)

regression=# EXPLAIN ANALYZE SELECT unique1 + unique2 FROM tenk1;
                                                QUERY PLAN                      
                          
--------------------------------------------------------------------------------
--------------------------
 Seq Scan on tenk1  (cost=0.00..470.00 rows=10000 width=8) (actual time=0.030..3
1.187 rows=10000 loops=1)
 Total runtime: 50.688 ms
(2 rows)

現状のplv8にできること。

  • int2/int4/int8/float4/float8/boolを適切にJavaScriptの値と相互変換する(pg:1 => js:"1"ではなくjs:1)
  • 上記以外は文字列形式を介して相互変換
  • array(pg) <=> Array(js)の相互変換。要素は上記ルールによる。一次元配列のみ。

できないこと。

  • date(pg) <=> Date(js)は悩み中。
  • SPI呼出(これできないと、PLとしての立場ないかも。とはいえ自分には不要なので。。。)
  • 複合型、疑似型など
  • トリガ
  • RETURNS SETOF

うーん、あまりいらないものばかりだけど、どうしよう。

目下のユースケースとしては、DBデータ内でJSONテキストを生成してそのままテーブルに保存し、取り出し→クライアントJSに引き渡しという流れなので、JSONデータ型は特にないです(textです)。JSON型を定義するとしても、v8Objectはきれいにシリアライズできそうもないので、内部ではJSONテキストをそのまま持つことになるでしょうね。。。それってあまりに非効率では、という意見もあるとは思いますが、GINインデックスを張るだけならextractValueしてくれるので元データの内部状態はなんでもいいんですね。実際XML型はテキストなわけです。

Makefileとかを汎用に作るのが億劫でまだ公開できるレベルではないですが、適当なタイミングで公開できればと考えています。

 |