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に放り込みます。