キーバリューデータベースのネストされたアイテムを効率的にクエリするためのスキーマをどのように設計しますか?
-
03-07-2019 - |
質問
MnesiaをErlangで使用していますが、この質問はcouchdbなどのすべてのキー値データベースに適用されます。
RDBMSの思考プロセスから解放しようとしていますが、できません。 この種のスキーマを効率的に実装する方法について説明します。
ユーザーレコードがあり、彼には多くのSubItemAレコードがあり、 多くのサブアイテムBレコード、したがって:
User
-SubItem A
--SubItem B
...
SubItem Bでクエリを実行する必要があります。 この入れ子?より速くなるように正規化するだけですか?
データの複製を使用している人がいるので、データは両方とも ネストされ、別々に、これはばかげていますか、これは実際に便利ですか ある場合?
解決
根本的な問題は、パフォーマンスがいつ十分であるかということです
すべてのSubItem Bを詳細に調べる必要があり、Bのサイズがディクショナリ全体のサイズを支配している場合、ユーザー辞書のテーブルスキャンは過度のオーバーヘッドではありません。
それで十分でない場合は、正規化して、SubItem Bを照会するときにすべてのUserおよびSubItem Aデータを読み取らないようにします。(UserId、SubItemAId、SubItemBId)などの複合キーを使用します範囲クエリを実行できるようにテーブルが順序付けられている場合は、サブアイテムBディクショナリ。
それによってユーザー/サブアイテムAのクエリパフォーマンスが完全に低下する場合、エラーが発生しやすいため、データの重複を最後の手段として検討してください。
他のヒント
CouchDbでは、各サブアイテムのビューエントリを発行するのは簡単です。これにより、これらのアイテムに非常に高速にアクセスできます。ビューエントリに入力した内容にもよりますが、おそらく親ドキュメント/サブアイテムにリンクするために必要な情報を提供できます。
Mnesiaについてはわかりませんが、CouchDBを使い始めたばかりですが、CouchDBでは、独自のカスタムインデックス(" views")を生成するので、簡単にインデックスを作成できますそれらのサブアイテム。
マップ関数の例:
function(doc) {
for(var i in doc.subitems_a) {
var subitem_a = doc.subitems_a[i];
for(var j in doc.subitems_a[item_a].subitems_b) {
var subitem_b = subitem_a.subitems_b[j];
emit(subitem_b, doc)
}
}
}
これは、事実上、サブアイテムBのインデックス付きリストであり、選択すると、そのリストから切り取ってスプライスできます。
実際には、使用しているデータベースによって異なります。 CouchDBでは、Mnesiaでは他の何かが優れているのに対して、1つのことがうまく機能します。データを分割して分割する必要がありますか?どのような基準でこれを行う必要がありますか?どのくらいのデータ複製で十分ですか?
ジェフリー・ハンティンが言ったように、適切な解決策を見つけるためにいくつかの実験と分析が必要です。つまり、ほとんどの非リレーショナルデータベースは、問題を解決するために必要なツールを提供します。あなたの役目は、それぞれのトレードオフと、他のトレードオフに対して受け入れることができるトレードオフを理解することです。