APIリクエストログを保存するために大きなデータウェアハウスで動的フィールドと値をサポートする必要があります。私のユーザーケースは、すべてのAPIリクエストクエリ文字列を保存し、将来的にそれらに対してクエリを実行できるようにする必要があるということです(ストレージだけではありません)。だから私はそれらにブロブを使うことはできません)
例えばhttp://example.com/?action=test&foo=abc&bar=def...
すべてのfield => value
マッピング、つまり(action => test), (foo => abc), (bar => def)
を格納する必要があります。フィールドは動的であるため、Entity-Attribute-Valueを使用するのが唯一の解決策ですが、非常に悪いデザイン。
それでは、上記の使用例を検討してください。EAVに代わる適切なものは何でしょうか。
KAVを使用する現在のスキーマ
テーブルrequests
(id, timestamp, uri)
例えば。 (1, 149382220, '/')
テーブルparams
(request_id, key, value)
例えば。 (1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')
助言がありますか?
更新:AWS RedShiftでウェアハウスを実行します
EAV、XML、およびスパース列の3つのソリューションを考えることができます。後者はベンダー固有であり、役に立たない場合があります。
どちらの方法を選択する場合でも、元の要求データを未加工の形式で、テーブルまたはフラットファイルに格納することを検討できます。これにより、データを保存する新しい方法を簡単に試すことができ、リクエストの解析方法に誤りを見つけた場合にデータを再ロードでき、バッチ処理または「ビッグデータ」を使用してAPIリクエストを解析する機会が提供されますデータウェアハウスがデータを効率的に処理できないことが判明した場合のツール。
EAVに関する考慮事項
EAV/KVSは、上記で説明したように、最も単純な実装である可能性があります。
残念ながら、これも非常にコストがかかります。一般的に使用されるキーに対して何らかの効率的なクエリを実行するには、非常に断片化する可能性のあるキー列にインデックスが必要です。特定のキーのクエリは非常に負荷がかかります。
関心のあるキーまたは値をクエリするためのマテリアライズドビュー(多くのベンダーがこれをサポートしています)でEAVストアをサポートすることにより、インデックス作成またはインデックススキャンのコストを削減できる場合があります。
[〜#〜] xml [〜#〜]
ほとんどのエンタープライズデータベースシステムは、検証、インデックス作成、高度なクエリなど、非常に成熟したXML処理を提供します。
API要求をXMLとしてデータベースにロードすると、要求ごとに1つのタプルが提供されます。論理的には、EAVテーブルに不明な数の行がある場合よりも少し口当たりが良いかもしれません。
これが効率的かどうかは、RDBMSベンダーと実装に大きく依存します。
最大の欠点は、これがおそらく、元のリクエストの文字列操作よりも複雑なデータを管理する唯一の方法であることです。
スパース列/従来のテーブル
キーごとに1つの列を使用して、データを従来のテーブル構造にロードできる可能性があります。
SQL Serverの Sparse Columns 機能は、EAVストアの優れた代替手段です。スパース列を含むテーブルは、最大30,000の列を持つことができることと、スパース列のNULL値がテーブルの領域を消費しないことを除いて、通常のテーブルとほとんど同じように動作します。
これらをフィルターインデックス(別のSQL Server固有の機能)と組み合わせると、特定の列や値を頻繁に照会する場合に、EAVストアの非常に効率的な代替手段を提供できます。
他のベンダーで従来のテーブルを使用することは現実的かもしれません-IBMはテーブルごとに700列以上、Oracleは約1000をサポートし、圧縮やOracleによる後続のnullの処理などの機能は、APIデータをかなり効率的に格納できることを意味します。
このアプローチの明らかな欠点は、APIに新しいキーを追加したときに、それに応じてスキーマを調整する必要があることです。
EAV自体は悪い設計ではありません。それは、かなりの量の先見性を必要とする単なる設計であり、データの量が増えるにつれてパフォーマンスの問題が発生する可能性があります。それはあなたのシステムにとってはうまくいくかもしれません。
クエリ文字列を保存するためのシステムを設計したとき、どのフィールドに興味があるのかわかりませんでした事前にクエリ文字列をシリアル化されたバイナリ形式で保存するためのテーブルを作成し、興味のある部分がわかったら、クエリ文字列を構成要素に分割することができました。そこから一連のテーブルを作成しました。クエリ文字列内に一般的に含まれるデータのセットごとに1つずつ。
たとえば、最終的にはリファラーデータ用のテーブルがあり、1つはターゲットリクエストデータ用で、もう1つはユーザーが入力した検索クエリなどのユーザー関連アイテム用です。
クエリ文字列全体を単一のテーブルにblobとして保存する機能が見つかりましたが、将来的にそのblobを分割する機能も提供され、私のニーズを非常に満たしました。