web-dev-qa-db-ja.com

Postgresの分析テーブルのスキーマ

分析にはPostgresを使用しています(スタースキーマ)。数秒ごとに、約500のメトリックタイプに関するレポートを取得します。最も単純なスキーマは次のとおりです。

timestamp      metric_type     value
78930890       FOO              80.9
78930890       Zoo              20

私たちのDBAは、同じ5秒間のすべてのレポートを次のようにフラット化することを提案しました。

timestamp   metric1     metric2     ...  metric500
78930890    90.9        20          ...  

一部の開発者は、これは開発(データをバッチ処理して1ショットで書き込む)を非常に複雑にし、保守性を向上させる(テーブルを見たりフィールドを追加するのはより複雑です)と反論します。

DBAモデルはそのようなシステムの標準的な方法ですか、それとも元のモデルが明らかに十分にスケーラブルでない場合の最後の手段ですか?

編集:最終的な目標は、ユーザーのために折れ線グラフを描くことです。そのため、クエリは主にいくつかのメトリックを選択し、時間/分で折りたたみ、1時間あたりの最小/最大/平均(または他の期間)を選択します。

編集:DBAの主な議論は、行数を500倍に減らすことで、より効率的なインデックスとメモリが可能になることです(この最適化前のテーブルには数億行が含まれます)。次に、複数のメトリックを選択するときに、推奨されるスキーマにより、メトリックごとに個別のインデックス検索を行う代わりに、データを1回通過させることができます。

編集:500メトリックは「上限」ですが、実際にはほとんどの場合、5秒あたり最大40メトリックのみが報告されます(ただし、40は同じではありません)。

5
user2976991

コメントされているように、両側からの引数は有効です。それらを「スター」(DBAのフラット化されたスキーマ)および「EAV」(エンティティー属性値)と呼びましょう。後者はヒントとして役立ちます。この関連回答の詳細:
このデータベース構造に名前はありますか?

500メトリックがよく知られているタイプで、新しいものを発明したり、古いものを常にドロップしたりしない場合、それは最悪のEAVシナリオではありませんが、同様です。

それを行う「標準」の方法はありません。より柔軟なアプローチは、「EAV」スキーマです。次に、メトリックタイプを簡単に追加および削除できます。参照される_metric_type_テーブルに行を追加するか、または1つを削除します(メトリックテーブルにカスケードします)。これにはスキーマの変更が必要であり、「スター」モデルではより高価になります。

どちらのモデルでも、スマート カバーリング/パーシャル/マルチカラムインデックス でかなりのことができます。

いくつかの決定ガイダンス

singleメトリックタイプの集約(min/max/avg/...)? ->「スター」
集計は、すべてまたは多くの異なるメトリックを考慮していますか? ->「EAV」

これらの属性は共通のエンティティを記述していますか? ->「スター」
それとも、他の方法でグループ化/分割できる数の集まりですか? ->「EAV」

あなたのデータは一度書き込まれ、その後変更されることはありませんか? ->「スター」
または、選択したメトリックに対して更新を実行しますか? ->「EAV」

500のメトリックのセットは完了していますか?セットはほとんどまたはまったく変更されませんか? ->「スター」
新しいメトリックが追加され、既存のメトリックは常に削除されますか? ->「EAV」

収納サイズ

コメントについて:

ストレージは最適化にとって重要ではなくなり、クエリ時間に焦点を合わせています。

ストレージサイズは、クエリ時間のmajor係数です。クエリを満たすために読み取る必要があるデータページの数は、おそらくパフォーマンスにとって最も重要な単一の要素です。

ささいな発言から始めましょう:_Data type is int or double_。

intは4バイトを占有します。
doubleは8バイトを占有します。

すべての列が_NOT NULL_であると仮定すると、500の整数列に1のタイムスタンプと行のオーバーヘッド(パディングなし)を加えたものは、「スター」スキーマで2036バイトを占有します。圧縮はできません。これを計算する方法は次のとおりです。
読み取りパフォーマンスのためのPostgreSQLの構成

intdoubleを混在させる場合は、パディングのためにスペースを無駄にしないようにしてください。たとえば、整数と倍精度のメトリックをグループ化します。

「EAV」モデルでは、行ごとに少なくとも44または52バイトが必要です。 1つのタイムスタンプに22000または26000バイト。 11-13倍。それは重要です。 1時間分のデータの場合、「スター」スキーマでは約180ページではなく、2000以上のデータページ(デフォルトのページサイズ8k)をフェッチする必要があります。

サイズを測定するいくつかのツールを次に示します。
PostgreSQLテーブル行のサイズを測定

ここでのパフォーマンスの鍵はストレージサイズにあると思います。あなたが_focusing on query times_であり、私が大まかな推測をしなければならなかった場合、 "star"スキーマがおそらくより良い選択です

しかし、私が言ったように、それは多くの詳細に依存します。


どちらの方法でも、クロス集計(「ピボットテーブル」)に興味があるかもしれません。 tablefunc modulecrosstab()関数を提供します:
集計関数グループの結果が1行になる

2