スタースキーマデータウェアハウスの動的フィールドのEAVの代替


13

APIリクエストログを保存するために、大きなデータウェアハウスで動的なフィールドと値をサポートする必要があります。私のユーザーケースは、すべてのAPIリクエストクエリ文字列を保存し、将来それらに対してクエリを実行できるようにすることです(したがって、単なるストレージではなく、だから私は彼らのためにブロブを使用することはできません)

例えば http://example.com/?action=test&foo=abc&bar=def...

すべてのfield => valueマッピングを保存する必要があります。つまり(action => test), (foo => abc), (bar => def)、フィールドは非常に動的であるため、私が見つけた唯一の解決策はEntity-Attribute-Valueを使用することですが、人々は非常に悪いデザインだと言い続けています。

それで、上記の私のユースケースを考えてください、EAVに適した代替物は何でしょうか?

KAVを使用した現在のスキーマ

  1. テーブルrequests
    (id, timestamp, uri)
    (1, 149382220, '/')

  2. テーブルparams
    (request_id, key, value)
    (1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

助言がありますか?

更新:AWS RedShiftでウェアハウスを実行します


2
開発データベースで提案していることを試してみて何が問題になっていますか?また、SQL Serverについて話しているのですか?SQLタグはかなり広いです。
マックスヴァーノン

私の質問を更新しました
ハワード

1
どのDBMSを使用していますか?一部には非常に優れたテキストインデックス機能があるため、要求を格納するために「ロングテキスト」フィールドを使用することを排除しません。そうは言っても、提案するモデルを使用しても問題はありません。EAVは厳密な意味では、この非常に特定の目的のためにのみ使用されています。繰り返しになりますが、どのようなクエリを実行できるようにする必要がありますか?このモデルに対してこれらのクエリを試し、記述して、それが機能するかどうかを確認してください。
コリン 'tハート

1
どのRDBMSを使用していますか?SQL十分に具体的ではありません。あなたは二度尋ねられました。私は三番目です。
アーウィンブランドステッター

2
RedShiftはPostgreSQLに基づいているため、hstoreまたはjsonデータ型を使用しようとします(またはjsonb9.4に「アップグレード」する場合)。
コリン 'tハート

回答:


11

EAV、XML、およびスパース列の3つのソリューションを考えることができます。後者はベンダー固有のものであり、役に立たない場合があります。

どちらの方法を選択する場合でも、元の要求データを生の形式で、テーブルまたはフラットファイルに保存することを検討できます。データを保存する新しい方法を簡単に試すことができ、リクエストの解析方法の間違いを発見した場合にデータをリロードできるようにし、バッチ処理または「ビッグデータ」を使用してAPIリクエストを解析する機会を提供しますデータウェアハウスがデータを効率的に処理できないことがわかった場合のツール。

EAVの考慮事項

上記で説明したように、EAV / KVSは最も簡単な実装である可能性があります。

残念ながら、それは非常に高価になります-一般的に使用されるキーであらゆる種類の効率的なクエリを取得するには、キー列にインデックスが必要であり、非常に断片化する可能性があります。特定のキーのクエリは非常に高価です。

EAVストアをマテリアライズドビューでサポートすることにより、インデックス作成またはインデックススキャンのコストを削減できる場合があります(多くのベンダーがこれをサポートしています)。

XML

ほとんどのエンタープライズデータベースシステムは、検証、インデックス作成、高度なクエリなど、非常に成熟したXML処理を提供します。

APIリクエストをXMLとしてデータベースにロードすると、リクエストごとに1つのタプルが提供されます。これは、EAVテーブルに不明な数の行があるよりも論理的には少々魅力的です。

これが効率的かどうかは、RDBMSベンダーと実装に大きく依存します。

最大の欠点は、これがおそらく元のリクエストの文字列操作よりも複雑なデータを管理する唯一の方法であることです!

スパース列/従来のテーブル

キーごとに1列のデータを、従来のテーブル構造にロードできる可能性があります。

SQL Serverのスパース列機能は、EAVストアの優れた代替手段です。スパース列のあるテーブルは通常のテーブルとほとんど同じ動作をしますが、最大30,000列を持つことができ、スパース列のNULL値はテーブル内のスペースを消費しません。

それらをフィルターインデックス(別のSQL Server固有の機能)と組み合わせることで、特定の列や値を頻繁にクエリする場合、EAVストアの非常に効率的な代替手段を提供できます。

他のベンダーで従来のテーブルを使用することは実行可能かもしれません-IBMはテーブルあたり700カラム以上、Oracleは約1000をサポートし、圧縮またはOracleの後続ヌルの処理などの機能は、APIデータをかなり効率的に格納できることを意味します。

このアプローチの明らかな欠点は、APIに新しいキーを追加したときに、それに応じてスキーマを調整する必要があることです。


2
PostgreSQLでは、XMLはお勧めしませんが、hstoreまたはのいずれかjsonです。今後の9.4では、jsonb私の推奨事項になります。
コリン 'ハート

長所短所とそれぞれの説明でこの答えが本当に好きです。非常に有益な情報-Sparse Columns情報に間違いなく感謝しています。疎列アプローチを使用したEAVの例をご覧ください。
StixO

9

EAVは、それ自体が悪い設計ではありません。それは単にかなりの量の予測を必要とする設計であり、データの量が増加するにつれてパフォーマンスの問題が発生する可能性があります。それはあなたのシステムにとってはうまくいくかもしれません。

クエリ文字列を保存するシステムを設計したとき、どのフィールドに興味があるのか事前に知りませんでした。クエリ文字列をシリアル化されたバイナリ形式で保存するテーブルを作成し、クエリを分割できるシステムを構築しました興味のある部分がわかったら、そのコンポーネント部分に文字列を追加します。そこから一連のテーブルを作成しました。クエリ文字列内に一般的に含まれるデータセットごとに1つ。

たとえば、リファラーデータ用のテーブル、ターゲットリクエストデータ用のテーブル、入力した検索クエリなどのユーザー関連アイテム用のテーブルが最終的にありました。

クエリ文字列全体を単一のテーブルにblobとして保存する機能を見つけましたが、将来そのblobを分割する機能を提供することで、私のニーズを非常によく満たしました。


1
質問と回答の両方で、バイナリロングオブジェクトBLOBを意味する用語が使用されます。バイナリデータではなく文字について話しているため、(Character Long OBject)またはPostgreSQLのようなものを使用したいと思います。CLOBtext
コリン 'tハート

2
セッションオブジェクト全体を実際にシリアル化し、データベース全体を格納したため、バイナリフィールドを使用しました。
マックスヴァーノン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.