web-dev-qa-db-ja.com

Timeseries:SQLまたはNoSQL?

SQLとNoSQLの一般的な違い(または従来の違い)は気にしません。

現在、内部時系列のストレージを変更することを検討しています。これらにはすべて、さまざまなソースからの財務データが含まれています。現在、独自のデータベースにデータを保存しています。それは非常にNoSQLであり、独自のクエリ言語を持っています。

コミュニティの入力に興味があります。SQLデータベースにデータをどのように保存しますか? NoSQLよりもSQLを使用することには、特に時系列にはどのようなメリットがありますか?これをSQLに格納することを検討するのは私が狂っていますか?

私たちのデータセットは数百万の時系列で構成され、これらの約10%にはそれぞれ数百万のレコードが含まれています。時系列は階層的に編成されています:/ Market/Instrument/Value/Frequency、ここで:

  • 市場は証券取引所などであり、基本的には商品のコレクションであり、通常は類似した商品です。
  • 楽器は楽器です。これは指標(ブレント原油)、株式(GOOG)などになる可能性があります
  • 値は、計測器の複数のタイプのデータの1つです。これは、近い、高い、低いなどの可能性があります
  • 頻度は、特定の時系列値の頻度です。毎週、毎日、毎月、ティック、任意など.

データはSQLデータベースにどのように格納されますか? 1つの大きなテーブル(何かで分割されている場合があります)、市場または機器ごとに1つのテーブル、時系列ごとに1つのテーブル。

前もって感謝します。

33
Nicolas

一般に、そのような構造化データセットについては、ほとんどの日常業務(つまり、任意の時間からの小さなデータのプル)でより高速なカスタムデータ形式を記述できると思います。標準のDBツールに移行する利点は、アドホッククエリ、マルチアクセス、レプリケーション、可用性など、いくつかの追加機能にあります。標準ベースのデータストアを維持するための支援を雇うのも簡単です。

そのデータを格納するデータベースをセットアップするように求められた場合、次のようにします。

提案されたスキーマ

(1)コアデータは、それぞれが2つの列を含む多数の(1000の)個々のテーブルに配置されます:

  1. 時間:SQLのDATETIMEデータ型またはいくつかのエポックからの数値型(これは主キーです)
  2. 値:データに応じて適切に入力します。デフォルトでは単精度浮動小数点を使用しますが、固定小数点データ型の方が金融取引に適している場合があります。これはおそらくインデックス付けされていません。

これらのテーブルは非常に大きくなるため、(たとえば)年ごとに手動で分割することができます。ただし、システムのパフォーマンスを確認し、必要に応じて調整する必要があります。

これらのテーブルには一意の名前が必要であり、いくつかのオプションがあります。人間が読める形式(例:nyse_goog_dailyhighs_2010)または(私の好み)ランダムなものを使用できます。どちらの方法でも、メタデータテーブルのセットが必要であり、ランダムなテーブル名により、開発者は、推論することを意図していない名前に何も推論できなくなります。

(2)メタデータは、アプリケーションの必要に応じて、個別のテーブルに保存されます

メタデータを追跡するには、追加のテーブルまたはテーブルのセットが必要です。これらのテーブルには、交​​換、商品、値、頻度、日付範囲、来歴(データの出所)に加えて、必要なその他のデータが含まれます。これらはデータテーブル名にマップされます。

十分なデータがある場合、このルックアップは実際にテーブル名とデータベース名を提供し、一種の自己実装データシャーディングを許可します(それが用語の正しい使い方である場合)。しかし、私はそれを控えめに保持します。

次に、アプリケーションレイヤーで、メタデータテーブルにクエリを実行してデータの場所を特定し、ビッグデータテーブルで比較的単純なクエリを実行してデータを取得します。

利点:

  • 私の(比較的限られた)経験では、データベースは通常、少数の大きなテーブルよりも多数の小さなテーブルを簡単に処理できます。このアプローチにより、メンテナンスが容易になります(古いデータのパージ、破損したテーブルの再構築、バックアップからの作成/再ロード、新しいエンティティの追加など)。これにより、(たとえば)異なるレートのデータがある場合、または異なるデータタイプが必要な場合に、異なる種類のデータが完全に分離されます。

  • この細いテーブルの概念により、最も一般的なクエリであると私が疑うもの、つまり単一のエンティティからの連続した範囲のデータに対して、高速ディスクアクセスが可能になるはずです。ほとんどのデータアプリケーションはディスクI/Oが制限されているため、検討する価値があります。コメンターがすでに示唆しているように、これは列指向データベースの理想的なアプリケーションですが、自分のキャリアに賭けるのに十分な主流となっている列指向の製品をまだ見つけていません。このスキーマはかなり近づきます。

欠点:

  • 率直に言って、100または1000のテーブルがタイムスタンプ列にまったく同じデータを持っている場合、ディスク領域の約半分がタイムスタンプの格納に使用されます。 (実際、これは簡単なテーブル結合を実行する場合の要件です)。

  • テーブル名を保存して動的ルックアップを実行するには、多くのアプリケーションの複雑さと文字列操作が必要です。しかし、それでも代替案よりも優れているようです(以下で説明します)。

考慮事項:

  • 時間フィールドの丸めに注意してください。 (適切な場合)結合を有効にするのに十分な丸みを持たせたいが、あいまいにならないように正確にする必要があります。

  • タイムゾーンと夏時間に注意してください。これらはテストするのが難しいです。データストアにUTC要件を適用し(これが不人気になる可能性があります)、アプリケーションで変換を処理します。

バリエーション:

私が検討したいくつかのバリエーションは次のとおりです。

データの折りたたみ:時系列が等間隔の場合、1つのタイムスタンプ列と(たとえば)10個のデータ列を使用します。タイムスタンプは最初のデータ列の時間を参照するようになり、他のデータ列はそのタイムスタンプと次のタイムスタンプの間で等間隔であると想定されます。これにより、以前はタイムスタンプを保存するために使用されていた多くのストレージが節約されますが、クエリやアプリケーションが大幅に複雑になります。隣接する範囲の単一エンティティクエリで必要なディスクアクセスが少なくなりました。

多重化:複数の時系列が同じ時系列を使用することがわかっている場合は、1つのタイムスタンプと(たとえば)上記のように10個のデータ列を使用します。しかし、現在、各列は異なる時系列を表しています。これには、メタデータテーブルの更新が必要です。これは、テーブル名と列名へのルックアップではありません。収納スペースが減ります。クエリは単純なままです。ただし、連続する範囲であっても、単一エンティティのクエリでは、はるかに多くのディスクアクセスが必要になります。

メガテーブル:「多重化」の概念を極端にして、すべてのデータを列ごとに1つの時系列で1つのテーブルに入れます。これは、連続した範囲の単一エンティティクエリのために大量のディスクアクセスを必要とし、メンテナンスの悪夢になります。たとえば、新しいエンティティを追加するには、多くのTBテーブルでMODIFY TABLEコマンドが必要になります。

この形式の詳細については、以下のさまざまな回答を参照してください。 MySQLの列が多すぎます

完全に正規化されたテーブル:2列のテーブルを多数使用する代わりに、時間、データID、および値。これで、メタデータテーブルは、テーブル名や列名ではなくID値を検索するだけで済みます。これにより、アプリケーションレイヤーではなく、より多くのロジックをSQLクエリにプッシュできます。

ストレージの約2/3が正規化列で消費されるため、これは多くのディスク領域を使用します。

(dataid、timestamp)の主キーの順序を使用して、連続した単一のエンティティクエリを高速化できます。または、(timestamp。dataid)の主キーの順序を使用して、挿入を高速化できます。

ただし、これらのバリエーションを考慮した後でも、私の次の開発計画は、それぞれ2列のテーブルがたくさんあることです。それ、またはすぐに私よりも賢い誰かによって投稿される方法:)。

26
Pursuit

MongoDBを使用すると、コレクションをその場ですばやく作成できます。データを個別のデータベースに整理し、それらのデータベース内のコレクションを調べます。高速検索が必要な場合は、各シャードをシステムメモリ内に保持するために必要なメモリ量を検討してください。必要なラインに沿って進化する何か新しいものがあれば、社内のソリューションに固執するのはばかげています。良いイニシアチブのように聞こえます。

1
Dantalion