postgreSQLへの非同期問い合わせ

やってみたのでメモ。
pg_send_query または、pg_send_query_paramsを使う
で、postgreSQL側でクエリの実行中の時は、次の問い合わせはできないとのこと
pg_send_queryは

$db = pg_connect("db_name=db1");
pg_send_query($db , "select pg_sleep(3); select pg_sleep(3);");

のように複数のクエリを送信することも可能。但し、この場合、クエリは直列で実行されるので、6秒間かかることになる。
複数のクエリを並列に走らせるには、別セッションで行う必要がある為、

//並列クエリ数分接続を確保する
$db1 = pg_connect("db_name=db1", PGSQL_CONNECT_FORCE_NEW );
$db2 = pg_connect("db_name=db1", PGSQL_CONNECT_FORCE_NEW );
pg_send_query($db1 , "select pg_sleep(3);");
pg_send_query($db2 , "select pg_sleep(3);");

となる。pg_connectはPGSQL_CONNECT_FORCE_NEW を指定して新規接続を作成

結果の取り出しはpg_get_resultを順に実行。

pg_send_query($db , "select 'foo'; select 'bar';");

//fooの問い合わせ結果
$res = pg_get_result($db);
while($row = pg_fetch_row($res)){
}
//barの問い合わせ結果
$res = pg_get_result($db);
while($row = pg_fetch_row($res)){
}

以下、確認。

<?php
$connection_string = sprintf("dbname=%s user=%s password=%s", $db_name, $user, $password);
$db1 = pg_connect($connection_string, PGSQL_CONNECT_FORCE_NEW );
$db2 = pg_connect($connection_string, PGSQL_CONNECT_FORCE_NEW );
$querys = array(
"select 'a',pg_sleep(3);",
"select 'a',pg_sleep(3);",
);
$sql = join(" ", $querys );
$time = microtime(true);
pg_send_query($db1,  $sql);
sleep(6);
echo microtime(true) - $time."\n";
#-----
# 6.0032370090485

$time = microtime(true);
pg_send_query($db1,  "select 'a',pg_sleep(3);");
pg_send_query($db2,  "select 'a',pg_sleep(3);");
sleep(3);
#-----
# 3.0066850185394

$time = microtime(true);
pg_query($db1,  "select 'a',pg_sleep(3);");
sleep(3);
echo microtime(true) - $time."\n";
#-----
# 6.0041198730469

となり期待した結果となる。

今後、汎用的に使えるコードにしたらgithubに放り込みます。