実況

本間圭一
2012年8月16日 18時21分
ブログランキング・にほんブログ村へ

マルチクエリとパフォーマンス調査

コンテスト用のアプリ開発もほぼ終盤といったところです。
実装していくなかで大きな悩みのタネがapi自体のパフォーマンスが遅いということです。

使ってみたことがある方であればその微妙なパフォーマンスがわかっていただけると思います。

こればっかりはfacebook側の問題なのでいかにapiの呼び出しを少なくするかが重要だと感じています。
しかもJOIN句が使えないので、必ずクエリを2つに分けなければいけない状況が生まれます。

テストとして以下のFQLを実行します。
  • 全ての友達リスト
  • 指定の友達リスト内の友達
  • 全ての友達
$time_start = microtime(true);
//全ての友達リスト
$r1 = $facebook->api(array('method' => 'fql.query',
                               'query' =>'SELECT flid, owner, name FROM friendlist WHERE owner = me()',
                               'access_token' =>$access_token,
                               ));

//指定の友達リスト内の友達
$r2 = $facebook->api(array('method' => 'fql.query',
                               'query' =>'SELECT uid,name FROM user WHERE uid in ( SELECT uid FROM friendlist_member WHERE flid = 123456)',
                               'access_token' =>$access_token,
                               ));
//全ての友達
$r3 = $facebook->api(array('method' => 'fql.query',
                               'query' =>'SELECT uid,name FROM user WHERE uid in ( SELECT uid2 FROM friend WHERE uid1 = me() )',
                               'access_token' =>$access_token,
                               ));
$time_end = microtime(true);
$time = $time_end - $time_start;
print $time.'秒';

結果3.77555608749秒

かなり遅いですね。
私が勤めていたサイボウズ社では3秒超えたら人は遅いと感じるので改善する。
という教えがありました。
確かに遅い。

そこでFQLにはマルチクエリという取得方法が用意されているようです。
クエリをまとめて一度でapiに投げるという方法です。

$time_start = microtime(true);
$r = $facebook->api
(
    array
    (
        'method'=>'fql.multiquery',
        'queries'=>array
        (
            'q1' =>'SELECT flid, owner, name FROM friendlist WHERE owner = me()',
            'q2' =>'SELECT uid,name FROM user WHERE uid in ( SELECT uid FROM friendlist_member WHERE flid = 123456)',
            'q3' =>'SELECT uid,name FROM user WHERE uid in ( SELECT uid2 FROM friend WHERE uid1 = me() )'
        ),
        'access_token'=>$access_token
    )
);
$time_end = microtime(true);
$time = $time_end - $time_start;
print $time.'秒';
die();

結果1.00289821625秒

3.7倍の違いがでました。
体感でもかなりの速度差を感じます。

facebook apiを使う場合はクエリをまとめることがパフォーマンスアップの近道のようです。

余談ですがマルチクエリの数の限界を調べようとかなりの数を投げて見ましたが、
5つめぐらいからパフォーマンスが落ちました。
※facebookさんごめんなさいm(_ _)m
あまりクエリを投げすぎてもよろしくないですね。

マルチクエリですが、
記載した例の様な書き方だけでなく、
#q1の様に書いて前のクエリ結果を使ってさらにクエリを投げることもできるようです。
$r = $facebook->api
(
    array
    (
        'method'=>'fql.multiquery',
        'queries'=>array
        (
            'q1' =>'SELECT uid2 FROM friend WHERE uid1 = me()',
            'q2' =>'SELECT uid,name FROM user WHERE uid in ( SELECT uid FROM #q1 )'
        ),
        'access_token'=>$access_token
    )
);