TABLESAMPLEを使ってみた

最近、某ラーメンデータベースのユーザー、店舗、レビューを収集して、PostgreSQLに突っ込んで、いろいろ遊んでいるわけですが、個人的には、どんなラーメンのスープ(醤油、塩、味噌、豚骨醤油、豚骨魚介等々・・・)のレビューがアップされている=人気があるのかというのが気になっていて、年毎にそういう傾向を調べていました。

2007年ころから豚骨魚介のレビュー比率が増加しているなあ。そのへんから豚魚ブームが始まったんだっけ。
自分の好みからは豚魚って外れているので、そんなに実感はないけど・・・

まあ、それはどうでもいいのですが、こういうデータを先日リリースされた、PostgreSQL 9.5.0に突っ込んでいるわけです。
せっかくだから、9.5の機能も使ってみたいところですが、BRINを適用するにはデータ量が小さいし、収集データの更新は基本行わないので、UPSERTも使わない。
自分しか使わないデータだから、Row Level Secutityも使いようがない・・・

あ、TABLESAMPLEなら試せるんじゃないか?

TABLESAMPLE

これは9.5からSELECT文に追加された機能で、検索結果を指定したメソッド・比率によってサンプリングした結果を出力するというもの。
サンプリングした結果をMATERIALIZED VIEWに突っ込んで、そのマテビューに対して上記のスープ別分類を検索するSELECT文をかけてみた。

こんな感じでサンプリングした結果をマテビューに突っ込む。

CREATE MATERIALIZED VIEW review_sample AS SELECT * FROM review TABLESAMPLE BERNOULLI(1.0);

BERNOULLIというのがサンプリングのメソッド(BERNOULLIとSYSTEMの2種類が現状指定可能。その違いは・・・調べてないw)、その引数がサンプリング対象とするレート(パーセント)を示す。
今回は 10%, 5%, 3%, 1% を指定してサンプリングしてみた。

SELECT対象 レコード数
全レコード 212107
10.0%サンプル 21139
5.0%サンプル 10799
3.0%サンプル 6367
1.0%サンプル 2157

なお、TABLESAMPLEによって得られる結果は実行ごとに異なるので注意な。

サンプリング結果からの集計

上記のように、 10%, 5%, 3%, 1% サンプリングした結果を格納したマテビューから、スープ別のGROUP BYをとって、グラフ化してみた。

今回収集したデータだと、10%くらいまでなら、オリジナルとほぼ同じような結果が得られそうだ。それよりサンプリング比率が低くなると、ちょっと誤差が大きくなるっぽい。
まあ、20万件程度のデータ量だと、サンプリングする必要はそれほどないけれど、数千万件とか数億系のデータをからおおよその集計をしたい場合には、TABLESAMPLEを使って、間引いたデータから集計するというのもありかもしれませんね。