分析には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は同じではありません)。
コメントされているように、両側からの引数は有効です。それらを「スター」(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の構成
int
とdouble
を混在させる場合は、パディングのためにスペースを無駄にしないようにしてください。たとえば、整数と倍精度のメトリックをグループ化します。
「EAV」モデルでは、行ごとに少なくとも44または52バイトが必要です。 1つのタイムスタンプに22000または26000バイト。 11-13倍。それは重要です。 1時間分のデータの場合、「スター」スキーマでは約180ページではなく、2000以上のデータページ(デフォルトのページサイズ8k)をフェッチする必要があります。
サイズを測定するいくつかのツールを次に示します。
PostgreSQLテーブル行のサイズを測定
ここでのパフォーマンスの鍵はストレージサイズにあると思います。あなたが_focusing on query times
_であり、私が大まかな推測をしなければならなかった場合、 "star"スキーマがおそらくより良い選択です。
しかし、私が言ったように、それは多くの詳細に依存します。
どちらの方法でも、クロス集計(「ピボットテーブル」)に興味があるかもしれません。 tablefunc
module はcrosstab()
関数を提供します:
集計関数グループの結果が1行になる