実行中のプロセスに関する情報をログに記録するシステムがあります。実行中の各プロセスには、並行して実行される場合と実行されない場合がある一連のステップが含まれています。システムは、プロセスとそのステップに関する情報を 2 つの別々のテーブルに記録します。
CREATE TABLE pid (
pid integer,
start_time timestamp,
end_time timestamp,
elapsed bigint,
aborted integer,
label char(30)
);
CREATE TABLE pid_step (
pid integer,
step integer,
start_time timestamp,
end_time timestamp,
elapsed bigint,
mem bigint,
...
);
このpid_step
表には、各ステップに関するリソース使用量の統計が多数含まれています。ここではmem
、そのステップに割り当てられたメモリのバイト数を記録する列として簡略化しています。おそらく5秒間隔で、プロセスラベルごとにメモリ割り当てをサンプリングしたいので、それをプロットできます。次のような結果が必要です。
tick label mem
----------------------- ------ -----------
2014-11-04 05:37:40.0 foo 328728576
2014-11-04 05:37:40.0 bar 248436
2014-11-04 05:37:40.0 baz 1056144
2014-11-04 05:37:45.0 foo 1158807552
2014-11-04 05:37:45.0 bar 632822
2014-11-04 05:37:45.0 baz 854398
ログには、5 秒間隔でのリソース使用量のサンプルではなく、各プロセスとステップの開始と終了のタイムスタンプしか表示されないため、5 秒間隔ごとに実行されていたプロセス ステップを特定する最も効率的な方法を見つける必要があります (目盛り)。次に、割り当てられたメモリを集約します。私は 3 つの別々の試行を行いましたが、パフォーマンスのレベルは異なりますが、すべて同じ結果が得られました。簡潔にするために、各クエリとその説明プランを要点 ( https://gist.github.com/anonymous/3b57f70015b0d234a2de ) に入れますが、それぞれのアプローチについて説明します。
これは私の最初の試みであり、間違いなく最も直感的で保守が簡単です。個別のプロセス ラベルを で交差結合して、ラベル
generate_series
ごとに 5 秒の目盛りを生成し、pid
およびpid_step
テーブルで左結合します。左結合は「ゼロ フィル」効果を作成し、関連付けられたデータを持たないティックを削除しないようにします。残念ながら、このアプローチは最悪のパフォーマンスを示します (以下のベンチマーク リンクを参照)。これは、between t2.start_time and t2.end_time
述語が結合条件ではなく結合フィルターとして処理されるハッシュ結合の使用によるものだと思います。これは私の 2 回目の試みであり、パフォーマンスははるかに優れていますが、直感的で保守しにくいものです。「ゼロ フィル」アプローチは、クエリ 1 と同じです。ただし、 と の左結合を実行する前
pid
にpid_step
、最大プロセス経過時間とプロセス ステップの開始時間と終了時間に基づいて、関連付けられたデータを持つティックを事前に計算します。 . これにより、ティック述語とラベル述語の両方を結合条件として表現でき、結合フィルターを使用しないソート/マージ結合が可能になります。これは私の最後の試みであり、クエリ 2 とほぼ同じ直感性と保守性で最高のパフォーマンスを発揮します。ここでの最適化は、最大プロセス経過時間よりも小さいことが保証されている最大プロセス ステップ経過時間を使用することです。 CTE t3 の開始時にネストされた小さなループ。
理想的には、SQL をクエリ 1 と同じくらいシンプルで保守しやすいものにしたいのですが、クエリ 3 と同じように実行できます。パフォーマンスを向上させるインデックスやクエリ 1 のわずかな書き直しの方法でできることはありますか?
ベンチマーク結果: http://i.imgur.com/yZxdQlM.png