象と戯れ

2012-12-09

PL/v8は最もリッチなプロシージャ言語に。

23:44 | PL/v8は最もリッチなプロシージャ言語に。 - 象と戯れ を含むブックマーク はてなブックマーク - PL/v8は最もリッチなプロシージャ言語に。 - 象と戯れ

この記事はPostgreSQL Advent Calendar 2012の9日目だと思います。

PL/v8のことはもうご存知でしょうか。JavaScript実行エンジンのV8を組み込んだプロシージャ言語で、JavaScriptPostgreSQLを拡張することができます。PostgreSQL9.2ではJSON型がビルトインとしてサポートされたこともあり、PostgreSQL本体のリリース文の中に言及があるなど、こちらの知らないところで宣伝されていたりしてこっちがびっくりするときもしばしば。先日日本で開催されたHeroku Meetup #7に来ていたはずのWillもあっちこっちでPL/v8の宣伝してますね。

さて、つい先ほどPGXNにて1.3.01.2.1をリリースしました。1.2.1は1.2.0からのバグフィックス、1.3.0は新機能を盛り込んだバージョンになります。あまり日本語で機能全体を紹介したことがないので概要を公式ドキュメントからの抜粋で紹介します。

スカラユーザ定義関数

いわゆる普通のユーザ定義関数をサポートします。SELECT foo() FROM bar;といった使い方ですね。下記のような感じです。

CREATE 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;

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

行を返す関数

Set Returning Functionというやつです。generate_series()の類いですね。この場合はplv8.return_next()によって行を返します。

CREATE TYPE rec AS (i integer, t text);
CREATE FUNCTION set_of_records() RETURNS SETOF rec AS
$$
    // plv8.return_next() stores records in an internal tuplestore,
    // and return all of them at the end of function.
    plv8.return_next( { "i": 1, "t": "a" } );
    plv8.return_next( { "i": 2, "t": "b" } );

    // You can also return records with an array of JSON.
    return [ { "i": 3, "t": "c" }, { "i": 4, "t": "d" } ];
$$
LANGUAGE plv8;

SELECT * FROM set_of_records();
 i | t
---+---
 1 | a
 2 | b
 3 | c
 4 | d
(4 rows)

トリガのサポート

トリガもかけます。PL/pgSQLと同様の変数を利用することができます。

CREATE FUNCTION test_trigger() RETURNS trigger AS
$$
    plv8.elog(NOTICE, "NEW = ", JSON.stringify(NEW));
    plv8.elog(NOTICE, "OLD = ", JSON.stringify(OLD));
    plv8.elog(NOTICE, "TG_OP = ", TG_OP);
    plv8.elog(NOTICE, "TG_ARGV = ", TG_ARGV);
    if (TG_OP == "UPDATE") {
        NEW.i = 102;
        return NEW;
    }
$$
LANGUAGE "plv8";

CREATE TRIGGER test_trigger
    BEFORE INSERT OR UPDATE OR DELETE
    ON test_tbl FOR EACH ROW
    EXECUTE PROCEDURE test_trigger('foo', 'bar');

インライン関数のサポート

9.0以降でDO文で呼び出す関数をサポートしています。

DO $$ plv8.elog(NOTICE, 'this', 'is', 'inline', 'code') $$ LANGUAGE plv8;

データベースのデータ型に応じて自動的にJSのデータ型に変換

引数と戻り値のデータ型に応じて適当なJSのデータ型に変換します。

  • oid
  • bool
  • int2
  • int4
  • int8
  • float4
  • float8
  • numeric
  • date
  • timestamp
  • timestamptz
  • bytea
  • json (>= 9.2)

timestamptzまでは想像に難くないと思います。1.3.0ではbyteaとJSONを追加し、byteaは後ほど紹介するTypedArrayによって符号なし1バイト整数配列に変換されます。9.2以降のJSON型についてはJSON.parse()/stringify()を呼び出してJavaScriptのオブジェクトに変換されます。

プリペアドステートメントとカーソルを含むSPI周りのサポート

PL/pythonやPL/perlと同様にSPIによるデータベースアクセスが利用できます。基本的にはplv8.execute()によりSQLが発行できるのと、plv8.prepare()によってPlanオブジェクトを取得、fetch()やcursor()を呼び出す方法があります。

var json_result = plv8.execute( 'SELECT * FROM tbl' );
var num_affected = plv8.execute( 'DELETE FROM tbl WHERE price > $1', [ 1000 ] );
var plan = plv8.prepare( 'SELECT * FROM tbl WHERE col = $1', ['int'] );
var rows = plan.execute( [1] );
var sum = 0;
for (var i = 0; i < rows.length; i++) {
  sum += rows[i].num;
}
plan.free();

return sum;

サブトランザクション

SPI関連でサブトランザクションが自動的に発行されます。関数の途中でplv8.execute()が失敗しても、try/catchで復帰してそれまでのデータベースへの変更をロールバックした後に処理を継続することができます。

try{
  plv8.subtransaction(function(){
    plv8.execute("INSERT INTO tbl VALUES(1)");  -- should be rolled back!
    plv8.execute("INSERT INTO tbl VALUES(1/0)");-- occurs an exception
  });
} catch(e) {
  ... do fall back plan ...
}

ユーティリティ関数

plv8オブジェクト経由で各種ユーティリティ関数が提供されています。

  • plv8.elog(elevel, msg1[, msg2, ...])
  • plv8.quote_literal(str)
  • plv8.nullable(str)
  • plv8.quote_ident(str)

こちらはほぼ標準てきな内容です。さらに、plv8.find_functionを利用して別のユーザ定義関数をJS関数としてロードすることができます。

CREATE FUNCTION callee(a int) RETURNS int AS $$ return a * a $$ LANGUAGE plv8;
CREATE FUNCTION caller(a int, t int) RETURNS int AS $$
  var func = plv8.find_function("callee");
  return func(a);
$$ LANGUAGE plv8;

PL/v8はtrusted languageであるため、データベース外のリソース(ファイルシステム、ネットワーク)へのアクセスは制限されていますので、こうしたコードの再利用はfind_functionを利用すると便利です。

ウィンドウ関数API

1.3.0よりウィンドウ関数APIを利用できるのでユーザ定義ウィンドウ関数をPL/v8で作成することができます。ウィンドウ関数内ではplv8.get_window_object()を呼び出してウィンドウオブジェクトを取得し、APIを呼び出すことができます。

var winobj = plv8.get_window_object();
return winobj.get_current_position() + 1;

TypedArray

V8には変態的な機能があって、メモリの内容を直に配列化することができます。これはもともとブラウザのCanvasのサポートでピクセルメモリを高速に処理するために用意されているのですが、PL/v8ではこれを利用してbytea及び一部の配列をJSの配列に変換します。byteaの列に任意のバイナリデータを保存して、面倒なCユーザ定義関数を書く変わりにJSで処理してしまうことも可能です。また、int2/int4/float4/float8についてはドメイン型plv8_int2array/plv8_int4array/plv8_float4array/plv8_float8arrayが用意されており、これらを引数として与えると一次元でNULLを含まない配列に対して高速なメモリアクセスが可能です。

create table foo(i, ary) as
  select i, ary from(select array_agg(a) ary
  from generate_series(1, 100000)a)a, generate_series(1, 100)i;

create or replace function int4sum(ary plv8_int4array) returns int8 as $$
  var sum = 0;
  for (var i = 0; i < ary.length; i++) {
    sum += i;
  }
  return sum;
$$ language plv8 immutable strict;

select int4sum(ary) from foo;
Time: 48.882 ms

-- plv8_int4arrayのかわりにint4[]を使った場合
Time: 820.785 ms

もうC言語関数いらないかもしれませんね。

リモートデバッガ

1.3.0からはd8を利用したデバッガを利用することができます。make時にENABLE_DEBUGGER_SUPPORTを定義するとデバッガ用のポートを開きます。デフォルトは35432番で待っています。

$ d8 --remote-debugger --debugger-port=35432

Node.jsなどではお馴染みのようです。

実行環境とユーザの隔離について

その他のPLでも同様の問題があるように、V8についてもユーザを切り替えた際に実行環境が混じらないように、それぞれのユーザごとにV8実行環境が作成されます。SET ROLEコマンドを使って同一接続中にユーザを切り替えた場合はグローバル変数などが別に定義されます。

スタートアップ処理

plv8.start_procに定義済みのJS関数名を記述することにより、毎回のJSエンジン初期化時にその関数が呼び出されます。これはグローバル変数/関数の準備などをするために有用です。

SET plv8.start_proc = 'plv8_init';
SELECT plv8_test(10);

JS方言のサポート

現在のところ、CoffeeScriptとLiveScriptが利用可能です。それぞれ別のExtensionになっていますので、利用したい場合はCREATE EXTENSIONを呼び出してください。特にLiveScriptについては、かのPugsを開発者Audrey Tangからパッチをもらっています。

----

さていかがでしょうか。PostgreSQLに標準でついてくるPL/pythonなどに比べても機能的に足りないところはなく、ウィンドウ関数やデバッガの機能などは寧ろ勝っていると言えるでしょう。またPL/v8の重要な特性の一つとしてtrusted languageがあり、セキュリティ上の理由からPL/pgSQLしか利用できなかった場面でもPL/v8が利用できます。特にPaaSなどではここが重要になるかもしれません。しかしPL/pgSQLに対して処理速度は圧倒的でありますので、よほどの理由(Oracleポーティングとか?)でないかぎりPL/pgSQLでないとだめという理由は見当たりません。強いて言えばJSには標準ライブラリ的なものはないので特有の問題を既存のライブラリで解決するなどのときはPL/pythonの方がいいとは思います。

というわけで、外様PLながらPL/v8は最もリッチなプロシージャ言語になってしまいました。本当はFDWとかも書けるようにしたいのですが、いかんせんネットワーク処理はできないのであまり有用ではないと思われます。その他、他に不足する部分があればどしどしIssueListにご応募ください。

Enjoy!

2011-12-10

Planet PostgreSQL chases Advent Calendar!

16:21 | Planet PostgreSQL chases Advent Calendar! - 象と戯れ を含むブックマーク はてなブックマーク - Planet PostgreSQL chases Advent Calendar! - 象と戯れ

お気づきの方も多いと思いますが、no titleにてAdvent Calendarを追跡中です。・・・が、どうもYahoo PipseとGAEの組み合わせが悪いようでPipseの更新を自動で反映できず、たまに私がデータの更新日付を1年前に戻して再取得させている・・・という涙ぐましいお話。

ちなみにYahoo Pipseは下記の要領で動いています。

ATNDのコメントRSSを取得

各リンクURLを収集

URLから当該ページのRSSを取得

タイトルまたは本文にPostgreSQL Advent Calendarの文字列が含まれるエントリを抽出

新しいRSSとして再構成

という流れになっています。初めてPipse触ったんですが、見た目のファンシーさの割にできることがわかりにくく・・・結局3時間ぐらいかかったので自前でプログラム書いた方が早かったんじゃというツッコミもありつつ、まあできたので良しと。上記の通り文字列抽出をしているのでAdvent Calendar本体の記事から程なく別目的で同様の文字列を含むエントリをアップした場合誤認識する可能性があります。なんでURLマッチしないんだと言われそうですが、いろいろあって結論からいうとPipseではUNIONできてもJOINできないんですねこれが。

というわけで各エントリをアップ頂いている皆々様には感謝の言葉に尽きますが、Yahoo Pipseからのアクセスがトップになっているからといって私に後ろ指ささないように・・・

2011-12-02

Heroku Postgresを触ってみた PostgreSQL Advent Calendar #2

16:28 | Heroku Postgresを触ってみた PostgreSQL Advent Calendar #2 - 象と戯れ を含むブックマーク はてなブックマーク - Heroku Postgresを触ってみた PostgreSQL Advent Calendar #2 - 象と戯れ

PostgreSQL Advent Calendar 12/2。もちろん日本時間で進行してます。

さてあまりディープな話しても仕方ないかなと思い、今話題絶頂渋谷女子高生の間でも噂になっていると言われるHeroku Postgresを早速使ってみた感想。ご存じない方のために念のため説明しておくと、HerokuがクラウドサービスとしてPostgreSQL単品で使えるサービスをこの間から提供しています。Database As A Serviceというやつか。

Postgres - SQL Database Service | Heroku

まずはログイン。Webサービスの方は無料から始められるけど、Postgresは最低月200ドルの有料サービスなのでクレジットカードを登録。Postgresの方とWebとでシングルサインオンです。

ログインしてデータベース作成。マジで2クリックぐらいです。できあがるとこんな感じ。

f:id:umitanuki:20111201230105p:image

フルAjaxでさくさく動きます。データベース名やユーザ名、パスワードはランダム文字列が勝ってに割り振られますが、右上のConnection Settingの矢印からpsqlを選ぶとコピペでそのままシェルキックできる文字列を作ってくれます。ついでにJDBCActiveRecord用文字列も作ってくれます。

SSL必須なのでソースインストールでpsql使っているようなマニアックな方はぜひ--with-opensslでビルドしなおしてください。っていうかこのオプション指定したことなかったアルよ。あ、おしゃれな六本木のお兄さんはもちろんpgAdminとかで接続してね。

psqlでログインすると何のからくりもないバニラPostgresです。\cでtemplate1にもつながります。おもむろにCREATE DATABASEすると権限がないとおこられます。\lはこんな感じ。

dv2jnpm7g28edxm=> \l
                                               List of databases
      Name       |      Owner      | Encoding |   Collate   |    Ctype    |          Access privileges          
-----------------+-----------------+----------+-------------+-------------+-------------------------------------
 dv2jnpm7g28edxm | uv25d4bx5cii4b0 | UTF8     | en_US.UTF-8 | en_US.UTF-8 | uv25d4bx5cii4b0=CTc/uv25d4bx5cii4b0+
                 |                 |          |             |             | collectd=c/uv25d4bx5cii4b0
 postgres        | postgres        | UTF8     | en_US.UTF-8 | en_US.UTF-8 | postgres=CTc/postgres
 template0       | postgres        | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres                        +
                 |                 |          |             |             | postgres=CTc/postgres
 template1       | postgres        | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres                        +
                 |                 |          |             |             | postgres=CTc/postgres
(4 rows)

9.0でDO構文使えますので

dv2jnpm7g28edxm=> do $$ declare begin raise 'hoge'; end; $$;
ERROR:  hoge

とかも動きました。

システムカタログもpg_authidとか以外は普通に見えるので、pg_pltemplateをのぞいてみました。

dv2jnpm7g28edxm=> select * from pg_pltemplate;
  tmplname  | tmpltrusted | tmpldbacreate |      tmplhandler       |        tmplinline        |   tmplvalidator   |    tmpllibrary    | tmplacl 
------------+-------------+---------------+------------------------+--------------------------+-------------------+-------------------+---------
 plpgsql    | t           | t             | plpgsql_call_handler   | plpgsql_inline_handler   | plpgsql_validator | $libdir/plpgsql   | 
 pltcl      | t           | t             | pltcl_call_handler     |                          |                   | $libdir/pltcl     | 
 pltclu     | f           | f             | pltclu_call_handler    |                          |                   | $libdir/pltcl     | 
 plperl     | t           | t             | plperl_call_handler    | plperl_inline_handler    | plperl_validator  | $libdir/plperl    | 
 plperlu    | f           | f             | plperl_call_handler    | plperl_inline_handler    | plperl_validator  | $libdir/plperl    | 
 plpythonu  | f           | f             | plpython_call_handler  | plpython_inline_handler  |                   | $libdir/plpython  | 
 plpython2u | f           | f             | plpython_call_handler  | plpython_inline_handler  |                   | $libdir/plpython2 | 
 plpython3u | f           | f             | plpython3_call_handler | plpython3_inline_handler |                   | $libdir/plpython3 | 
(8 rows)

ん?先日の話だと「安全じゃない(untrusted)言語なんて導入できない」とか言ってたような。

dv2jnpm7g28edxm=> create language plperl;
ERROR:  could not access file "$libdir/plperl": No such file or directory

なるほど。共有オブジェクト置いてないんですね。っていうかそれならpg_pltemplateからはずしとけよって気もしますが。パッケージインストールなのかな?

そのうちここにplv8jsが並ぶわけですね。わかります。

dv2jnpm7g28edxm=> create table t(a, b, c) as select i, i % 100, repeat('x', 100 + i % 100) from generate_series(1, 1000000)i;
SELECT 1000000
Time: 23165.819 ms

dv2jnpm7g28edxm=> select pg_size_pretty(pg_database_size('dv2jnpm7g28edxm'));
 pg_size_pretty 
----------------
 189 MB
(1 row)

Time: 107.376 ms

dv2jnpm7g28edxm=> select count(*) from t;
  count  
---------
 1000000
(1 row)

Time: 937.279 ms

手元のMacBookでやったらCTASは4秒ぐらいで終わったのでやっぱり書き込みはちょっと遅いですね。もちろんWAL設定が手元はデフォルトなんですが。ただ参照は手元と同じぐらいかちょっと早いぐらい。キャッシュが1.7Gでテーブル作成は自由にできて参照もこのぐらい出るのならば、なんかもうこれでいいかって気がします。ていうかこれで最低ランクなんですが、最高ランクのMechaって誰が月6400ドルも払って数十ギガのキャッシュのせるのか。面白いから用意してみたって匂いがぷんぷんするw。

さてさて目玉はレプリケーション。ポチットな。

f:id:umitanuki:20111201230106p:image

一回失敗しましたが、二回目で完成。ログもAjaxかWebSocketか知らないけどWeb画面開いたまま更新されていきます。もちろんこのFollowerも一台につき200ドル/月。

バックアップもワンクリック。リストアは新しいDBインスタンスになる模様。金稼ぐなー。バックアップのダウンロードもリンクのクリックでダウンロード始まります。形式は-Fcですね。

あ、ちなみに料金は月極の時間単位なので、11月31日の夜にDB作って早速2ドル請求が来ました。逆に言うとこうして実験してインスタンス破棄すれば200ドルもいらないわけです。ていうかこのぐらいの性能でレプリケーション、バックアップ、リストア、ログ管理等等を全く気にしなくていいとすれば、月200でサーバ+DBAなんか雇えないわけで、十分ペイする気がします。

そんなわけで長くなりましたが、Heroku Postgres使ってみました。

明日はitagaki.takahiroさんです。よろしう。


P.S.

pg_settingsをコピペしときます。興味のある人はご覧あれ。

dv2jnpm7g28edxm=> select name, setting from pg_settings;
              name               |                                                                  setting                                                                   
---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------
 allow_system_table_mods         | off
 application_name                | psql
 archive_command                 | test -f /etc/postgresql/9.0/main/wal-e.d/ARCHIVING_OFF || envdir /etc/postgresql/9.0/resource6279_heroku_com/wal-e.d/env wal-e wal-push %p
 archive_mode                    | on
 archive_timeout                 | 60
 array_nulls                     | on
 authentication_timeout          | 60
 autovacuum                      | on
 autovacuum_analyze_scale_factor | 0.1
 autovacuum_analyze_threshold    | 50
 autovacuum_freeze_max_age       | 200000000
 autovacuum_max_workers          | 3
 autovacuum_naptime              | 60
 autovacuum_vacuum_cost_delay    | 20
 autovacuum_vacuum_cost_limit    | -1
 autovacuum_vacuum_scale_factor  | 0.2
 autovacuum_vacuum_threshold     | 50
 backslash_quote                 | safe_encoding
 bgwriter_delay                  | 200
 bgwriter_lru_maxpages           | 100
 bgwriter_lru_multiplier         | 2
 block_size                      | 8192
 bonjour                         | off
 bonjour_name                    | 
 bytea_output                    | hex
 check_function_bodies           | on
 checkpoint_completion_target    | 0.7
 checkpoint_segments             | 40
 checkpoint_timeout              | 300
 checkpoint_warning              | 30
 client_encoding                 | UTF8
 client_min_messages             | notice
 commit_delay                    | 0
 commit_siblings                 | 5
 constraint_exclusion            | partition
 cpu_index_tuple_cost            | 0.001
 cpu_operator_cost               | 0.0005
 cpu_tuple_cost                  | 0.003
 cursor_tuple_fraction           | 0.1
 custom_variable_classes         | 
 DateStyle                       | ISO, MDY
 db_user_namespace               | off
 deadlock_timeout                | 1000
 debug_assertions                | off
 debug_pretty_print              | on
 debug_print_parse               | off
 debug_print_plan                | off
 debug_print_rewritten           | off
 default_statistics_target       | 100
 default_tablespace              | 
 default_text_search_config      | pg_catalog.english
 default_transaction_isolation   | read committed
 default_transaction_read_only   | off
 default_with_oids               | off
 effective_cache_size            | 191250
 effective_io_concurrency        | 1
 enable_bitmapscan               | on
 enable_hashagg                  | on
 enable_hashjoin                 | on
 enable_indexscan                | on
 enable_material                 | on
 enable_mergejoin                | on
 enable_nestloop                 | on
 enable_seqscan                  | on
 enable_sort                     | on
 enable_tidscan                  | on
 escape_string_warning           | on
 extra_float_digits              | 0
 from_collapse_limit             | 8
 fsync                           | on
 full_page_writes                | on
 geqo                            | on
 geqo_effort                     | 5
 geqo_generations                | 0
 geqo_pool_size                  | 0
 geqo_seed                       | 0
 geqo_selection_bias             | 2
 geqo_threshold                  | 12
 gin_fuzzy_search_limit          | 0
 hot_standby                     | on
 ignore_system_indexes           | off
 integer_datetimes               | on
 IntervalStyle                   | postgres
 join_collapse_limit             | 8
 krb_caseins_users               | off
 krb_srvname                     | postgres
 lc_collate                      | en_US.UTF-8
 lc_ctype                        | en_US.UTF-8
 lc_messages                     | en_US.UTF-8
 lc_monetary                     | en_US.UTF-8
 lc_numeric                      | en_US.UTF-8
 lc_time                         | en_US.UTF-8
 listen_addresses                | *
 lo_compat_privileges            | off
 local_preload_libraries         | 
 log_autovacuum_min_duration     | -1
 log_checkpoints                 | on
 log_connections                 | off
 log_destination                 | syslog
 log_disconnections              | off
 log_duration                    | off
 log_error_verbosity             | default
 log_executor_stats              | off
 log_hostname                    | off
 log_line_prefix                 | %u [ONYX] 
 log_lock_waits                  | off
 log_min_duration_statement      | 50
 log_min_error_statement         | error
 log_min_messages                | notice
 log_parser_stats                | off
 log_planner_stats               | off
 log_rotation_age                | 1440
 log_rotation_size               | 10240
 log_statement                   | none
 log_statement_stats             | off
 log_temp_files                  | -1
 log_timezone                    | UTC
 log_truncate_on_rotation        | off
 logging_collector               | on
 maintenance_work_mem            | 65536
 max_connections                 | 500
 max_files_per_process           | 1000
 max_function_args               | 100
 max_identifier_length           | 63
 max_index_keys                  | 32
 max_locks_per_transaction       | 64
 max_prepared_transactions       | 500
 max_stack_depth                 | 2048
 max_standby_archive_delay       | -1
 max_standby_streaming_delay     | -1
 max_wal_senders                 | 10
 password_encryption             | on
 plpgsql.variable_conflict       | error
 port                            | 5432
 post_auth_delay                 | 0
 pre_auth_delay                  | 0
 random_page_cost                | 4
 search_path                     | "$user",public
 segment_size                    | 131072
 seq_page_cost                   | 1
 server_encoding                 | UTF8
 server_version                  | 9.0.5
 server_version_num              | 90005
 session_replication_role        | origin
 shared_buffers                  | 53120
 silent_mode                     | off
 sql_inheritance                 | on
 ssl                             | on
 ssl_renegotiation_limit         | 524288
 standard_conforming_strings     | off
 statement_timeout               | 0
 superuser_reserved_connections  | 3
 synchronize_seqscans            | on
 synchronous_commit              | on
 syslog_facility                 | local0
 syslog_ident                    | resource6279_heroku_com
 tcp_keepalives_count            | 9
 tcp_keepalives_idle             | 7200
 tcp_keepalives_interval         | 75
 temp_buffers                    | 1024
 temp_tablespaces                | 
 TimeZone                        | UTC
 timezone_abbreviations          | Default
 trace_notify                    | off
 trace_recovery_messages         | log
 trace_sort                      | off
 track_activities                | on
 track_activity_query_size       | 1024
 track_counts                    | on
 track_functions                 | none
 transaction_isolation           | read committed
 transaction_read_only           | off
 transform_null_equals           | off
 unix_socket_group               | 
 unix_socket_permissions         | 511
 update_process_title            | on
 vacuum_cost_delay               | 0
 vacuum_cost_limit               | 200
 vacuum_cost_page_dirty          | 20
 vacuum_cost_page_hit            | 1
 vacuum_cost_page_miss           | 10
 vacuum_defer_cleanup_age        | 0
 vacuum_freeze_min_age           | 50000000
 vacuum_freeze_table_age         | 150000000
 wal_block_size                  | 8192
 wal_buffers                     | 1024
 wal_keep_segments               | 127
 wal_level                       | hot_standby
 wal_segment_size                | 2048
 wal_sender_delay                | 200
 wal_sync_method                 | fdatasync
 wal_writer_delay                | 200
 work_mem                        | 102400
 xmlbinary                       | base64
 xmloption                       | content
 zero_damaged_pages              | off
(196 rows)

うーん。shared_buffers=53120ってことは8KBかけて400MBですね。キャッシュって何のことなんだろう。。。

2011-11-25

SQL Server 2012の記事がひどすぎる件

14:26 | SQL Server 2012の記事がひどすぎる件 - 象と戯れ を含むブックマーク はてなブックマーク - SQL Server 2012の記事がひどすぎる件 - 象と戯れ

まあ今に始まったことではないかもしれませんが。。。

SQL Server 2012の全貌が見えてきた!新ライセンス体系、高可用性、見える化、インメモリ、そしてビッグデータ (2/3):EnterpriseZine(エンタープライズジン)

Enterpriseエディションならではの機能としてカラムベースのインデックス処理技術である「カラムストアインデックス」がある。Excel/SharePointのアドインである多次元インメモリ機能「PowerPivot」のカラムベースエンジン(VertiPack)をベースに、列(カラム)単位のインデックス格納を実現、データの圧縮率を大幅に高め、パフォーマンスを劇的に向上させる機能だ。斎藤氏によれば「件数にもよるが、フルテーブルスキャンに比べて100倍以上は高速になる」とのこと。日次集計など参照処理を行うデータウェアハウジングにおいて大幅な処理性能向上が期待できる。

カラム単位のインデックスって普通じゃね?インデックスって普通カラムに対して貼るものだよね??五味さんって以前もPostgreSQLかなんかの記事で意味不明なことを書いていた記憶があるからまあ記者なんてそんなもんだよねと思っていたら、Microsoftのページにも「Columnstore Index」って書いてあったなんだかなと思ったり。

Sign in to your Microsoft account

でよく読んでみると列圧縮(カラムコンプレッション)のことなんだと思う。ただしGreenplumのそれと違って元のテーブルはそのまま保存して列圧縮したデータを別に作るんだろうと思われる。なので「インデックス」と呼んでいるんだと思うんだけど、それって本質的にインデックスじゃないよね?? どっちかっていうとVerticaのマテリアライズドビューに近い気がする。だいたいあれですよ、Clustered Indexって奴だって、それ意味あるの??みたいな話でしょ。

ちなみに列圧縮はBIデータベースでは割とホットでして、元々列指向のVerticaやSybaseはともかく、Netizza、Teradata、Greenplumもサポート(予定)しており、ないと列強に加われないという明治時代の軍艦みたいなものです。あ、Oracle(Exadata)もサポートするとかしたとか。

Teradata Columnar and Teradata 14 compression | DBMS?2 : DataBase Management System Services

Jim Gray亡き今というか彼がいたからSQL ServerがBIっぽくなっちゃっただけで、MySQLみたいに「そういうのは関係ないですから」っていう方向を進めばよかったのに。

ジム・グレイ - Wikipedia

閑話休題。

AlwaysOnでは、最大4台のセカンダリサーバに複製可能で、自動/手動によるフェールオーバーが可能だ。セカンダリは同期モードと非同期モードに設定することができ、同期モードに設定すると「アクティブセカンダリ」として稼働させることができる。いつでもプライマリに取って代われるセカンダリ、という位置づけだ。これにより処理を負荷分散させながらコンピューティングリソースを使うことが可能で、高い可用性を維持できるという。デモでは東京⇔大阪間でのフェールオーバーが行われた場合、ダウンタイム15秒程度でセカンダリがプライマリのロールを引き継いで稼働するデモが実演された。ほぼリアルタイムの同期といっていいだろう。

15秒!?15秒でリアルタイムって呼んでいいの??何千件というトランザクションが消える(失敗する)と思うんですけど、いいんですね。それでいいんですね。WALをディスクに書くか、メモリに書くかですったもんだ議論しているPostgreSQLのレプリケーションはがんばりすぎですかね。もちろんフェイルオーバーが透過的にできるのは大事なことだと思いますけど、15秒ってひどくないですか。しかも最大4台とか。「カスケードしてもいい?」とかおちゃめなことを言ってるFujiiさんが泣きます。

まー総じてSQL Serverのテクノロジっていつの時代もこんなかんじで「えっ?」って話が多いような気がするけど、実際自分がその業界に行ってみてわかった、SQL ServerをBIで使ってるところはないに等しい(笑)もちろん小規模でOLTPと並行でBIツールと使ってるところはあるけれども、大規模でいうと Teradata、Oracle、Netizza、Greenplum、たまにSybaseとかAsterとかVerticaとかいう話はあっても、SQL Serverはないね。それでも大企業のバックエンドでWindowsサーバーと抱き合わせで使ってる人たち、かわいそうになあ、っていつも思うけど。Jとか。レプリケーションの怠慢っぷりに何度となく泣かされておりましたもので。まったくMSの誇大広告には目に余るものがある・・・

2011-11-09

Herokuオフィスに行ってPostgreSQLとpl/v8の話聞いて来た

17:04 | Herokuオフィスに行ってPostgreSQLとpl/v8の話聞いて来た - 象と戯れ を含むブックマーク はてなブックマーク - Herokuオフィスに行ってPostgreSQLとpl/v8の話聞いて来た - 象と戯れ

f:id:umitanuki:20111108222542j:image

f:id:umitanuki:20111108222513j:image

f:id:umitanuki:20111108223759j:image

f:id:umitanuki:20111108223824j:image

f:id:umitanuki:20111108224911j:image

SFPUG二回目。今日はHerokuオフィスで直々にPostgreSQLの話を聞いてきましたよ。

彼らはpure PostgreSQLを使っていて、ソースには全く手を入れていない。が、デモを見る限りAmazonPostgreSQLインスタンスをワンクリックで立ち上げてWALもばっちり保存(自作のWAL-Eとやらを使ってるらしい)。ストリーミングレプリケーションとホットスタンバイもWebの管理画面からワンクリックで追加。DBのスナップショットもワンクリック。まさにこれぞ象の群れと呼ぶべきかもしれない。

写真貼りますけどオフィスはサンフランシスコ市中にあっておしゃれなレンガ作りの建物を3フロアゆったり使ってオサレな感じ。雰囲気的にはCookPadが近いと思うけど、Ruby使いはいつもオサレだね。そんなオサレな連中がPostgreSQLに注目しているというのがまたホット。MySQLには全く興味がないってさ。

そんな彼らが今最も注目しているのがpl/v8。今俺触ってないって何回も言ってるのに「よくするにはどうしたらいいか」「このプロジェクトこそが今我々に最も必要だ」などとアツく語られてしまいました。やっぱHerokuのターゲットが小〜中規模のWebアプリをさくさく作ることにあるため、JavaScriptこそが最も使い勝手がいいらしい。おまけに速い(と彼らは思ってる)。メンバーの一人が作ったプレゼン↓

http://pgeu-plv8.herokuapp.com/

そんなわけでシャレで始めたplv8ですがHerokuだけでなく随分いろんな人が興味持ってるらしいしplv8開発者は絶賛期待されております。9.2か9.3にはJSONデータ型も入れてHerokuのデファクトにしたいってさ。そうなるとpl/perlやpl/pythonどころじゃなくなるかもねー

んだば