PL/PGSQLでダウンサンプリングしたい

Azure

先日あるお客様との会話で、膨大なデータをグラフにするのに、pg_cronでaggregation(事前集計)をかけておけば、そのグラフをダッシュボードでインタラクティブにスケールを変更しつつ、少ないデータをfetchするだけで良いので、むっちゃ軽快な動作をするようにできまっせ、という話になった。

で、aggregationの内容はハンズオンラボ用に書いたPL/PGSQLを見てもらえば分かる通り、AVG / MIN / MAXを取るだけなので、折れ線グラフにした時に特徴を表すかというと非常に微妙、という説明をしたところ、そのお客様がLTTB(Largest Triangle Three Buckets)アルゴリズムというのがあって、という情報を提供してくれた。

不勉強なもので知らなかったため調べてみると、Qiitaに書いてくれてる人がいるので、まあそこからたどってGitHubのまとめページに行き着いた。特に難しいことをやってるわけではないのだけれど、残念ながらPL/PGSQLで書いてる人がおらん。PL/PGSQLで書かれてれば、CREATE FUNCTIONしてpg_cronで定期的に呼び出してやりゃイイ訳で、じゃ書くかと午前中から書いて今に至る、と。

元データから描いた折れ線グラフ
PL/PGSQLでダウンサンプリングして描いたグラフ

GitHubに放流しておいた。

pg_cronで使うなら、largest_triangle_three_buckets()にクエリ結果とthresholdを引数として渡すように変更すればよろし。

追記:sin波をダウンサンプリングするとどうなるのか。

-- 100件にダウンサンプリングするクエリ
WITH selected_data AS (
    SELECT array_agg(POINT(x, sin(radians(x)))) AS data_array
        FROM generate_series(-180, 180, 0.1) AS x
)

SELECT * FROM largest_triangle_three_buckets(
    (SELECT data_array FROM selected_data),
    100
);
3600レコード
100件にダウンサンプリング
50件
20件
10件

10件でも特徴は分かりそう。

タイトルとURLをコピーしました