LAN では一秒未満で表示されるフォームが VPN 経由では五秒かかる一方、同じ回線のファイルコピーは全速で流れる。違いは帯域ではない。フォームは一連の応答を待ち、各段階で往復を丸ごと支払うのに対し、ファイルコピーはバイトを途切れなく流し続ける。アクセス回線に触れる前に、その待ちを数えてほしい。

症状はクエリではなく画面である

その画面のどのクエリも速くても画面は遅くなりうる。合計は実行時間の和ではなく待ちの和だからだ。二ミリ秒で走る文でも、次の問い合わせを送る前に結果を受け取らねばならないなら、往復一回分の費用がかかる。遅延が四十ミリ秒の経路では、依存した百回の呼び出しは描画が始まる前に約四秒へ積み上がる。この算術は待ちの模型であって、回線の実測ではない。

だから速度テストは無害に見える。一括転送はスループットを測り、おしゃべりなフォームは遅延を測る。VPN は一方に優れ、他方では平凡でありうる。画面を診断するとは、回線ではなく画面を測ることだ。

何かを変える前に、利用者の一操作の端から端までの時間を記録する。その数だけが、後日の修正が効いたかを教えてくれる基準線になる。

一つの操作のなかの逐次的な待ちを数える

推測せずクライアント側で測る。psql では \timing on が各文の経過時間を表示し、EXPLAIN (ANALYZE, BUFFERS) がその時間のうちサーバーが実際に作業に費やした分を示す。

この二つの数の差が、ネットワークとクライアントの負荷である。文が二ミリ秒で実行され、クライアントが六十と記録するなら、残りの五十八は移動とローカル処理であり、索引では消せない。画面が発するすべての文で同じ比較を繰り返し、実行時間ではなく差を足し上げる。

結果は逐次的な待ちの数として書き留める。次の二節が減らせるのはその量であり、証拠を挙げて論じられる数でもある。

独立した呼び出しをまとめ、依存するものは残す

互いの結果を読まない二つの文は一緒に運び、一度に回収できる。待ちが二つから一つになる。二つ目の文が一つ目の値を要する場合はできない。依存が実在し、まとめればプログラムの挙動が変わるからだ。書き換える前に呼び出しをこの二つの山に分ければ、それぞれの大きさが何をなしうるかを教えてくれる。

集合単位の処理は、まとめるより待ちを根本から除く。ループが一件ずつ取っていた行を一度に返すクエリは、往復だけでなくループ自体を消す。まずループを探すとよい。ふつうはそちらが大きな利益で、見直しも簡単な変更になる。

まとめても、誤り処理と トランザクションの境界 は保たねばならない。無関係な文を一つの文字列に連結するのは安全な最適化ではない。失敗した文を成功した送信の陰に隠すまとめは、節約した待ちより悪い。

帯域を買う前に接続を使い回す

新しい接続は名前解決、TCP の握手、TLS の交渉、認証を要し、遅延の大きい経路ではその一つ一つが最初のクエリまでの往復になる。接続プールは、呼び出しごとではなくプロセスごとに一度その費用を払うためにある。

ADO.NET では、プールされた接続を閉じるか破棄すると、新しい物理接続を開かずに再利用へ戻す。だから漏れに見える型がしばしば正しい使い方だ。プールが実際に使われているかを確かめ、思い込まないこと。物理接続の生成を記録するか、画面を動かしながらサーバーのセッション数を眺める。SQL の性能ガイダンス も往復の削減と頻繁なアドホック呼び出しのまとめについて同じことを述べ、自陣の配備に写すべきサービス固有の例を示している。

プールは設定費用を除くが、逐次的なクエリの待ちはそのまま残す。それ自体は修正ではなく、清潔な計測の前提である。

実行をデータの近くへ移すことを秤にかける

アプリをデータベースの近くで動かせば、多数の遠隔データベース往復が一つの遠隔表示セッションに置き換わる。おしゃべりな負荷には大きな変更になりうるし、性能の変更であると同時に運用の変更でもある。セッション管理、アクセス制御、ソフトウェア配備、利用者体験がアプリとともに移る。

どちらの向きが速いと決める前に、実際のインターフェースとそれが運ぶデータを測る。遠隔デスクトップのセッションは画素を運び、濃い図形の画面は同じ経路で、置き換えたクエリより劣ることがある。とくにクライアントが描き直し続ける場合にそうなる。

そのうえで元の操作を繰り返し、三つの数を比べる。逐次的な待ち、結果の量、端から端までの完了時間である。測った利用者の作業を変えつつ、データの正しさとアクセス方針を保つ改善こそ、残す価値がある。

関連記事