通知用のストレージとして mongo db を部分的に使用する製品があります。ほぼ 2 か月間ライブですが、深刻なパフォーマンスの問題に直面しています。通知の問題のために設計した構造を紹介しましょう。
3 つの基本的なコレクションがあります。
notification_item, notification_subscriptions and notification_actions
システム上のすべてのユーザー作成データは、notification_item
を含むowner
を作成しcreation_date
ます。meta data
次に、データの所有者 (最初のステップで作成されます) は、コレクション
notification_item
を通じてそのデータを購読します。(コレクションへの参照) と誰が購読したかで構成されます。notification_subscription
notification_subscription
notification_item's object id
notification_item
user_id
最後はnotification_action
コレクションです。任意の通知項目に対する任意のアクションが挿入されるのは簡単です。それは構造でありnotification_item's object id
、creation_date
そしてother meta data
。通知アクションを作成するすべてのユーザーは、その通知アイテムをサブスクライブして、さらに通知をリッスンします。
とにかく、これまでのドキュメントのサイズは count です。
notification_items = 4348
notification_subscription = 11324
と
notification_action = 12226
ほとんどの notification_items クエリを購読しているユーザーの notification_action でクエリを実行すると、問題が発生します。クエリの実行が非常に遅いです。
の数のユーザーがサブスクライブしたとしましょう
notification_items = 778
ローカルで 15 秒間実行され、そのユーザーのすべてのアクションが取得されます。これがクエリです(phpですが、同じ結果であるjavascriptでテストしました);
public function getNewNotificationsByUserId($id){
$loggingImpl = new LoggingImpl();
$subsColl = "notification_sub";
$cursor = $this->mongoDb->db->$subsColl->find(array("user_id" => "$id"));
$subs = array();
while($doc = $cursor->getNext()){
$subs[] = array("not_item._id" => $doc['not_item'],'creation_date' => array('$gte' => $doc['creation_date']));
}
$actions = array();
if(empty($subs)){
return $actions;
}
$actionColl = NotificationAction::COLL;
$query = array('$or' => $subs, 'owner.id' => array('$ne' => "$id" ));
$d1 = microtime(true);
$cursor = $this->mongoDb->db->$actionColl->find($query)->sort(array('creation_date' => -1));
while($doc = $cursor->getNext()){
$actions[] = $doc;
}
$d2 = microtime(true);
$loggingImpl->logDebug("notification data:".($d2-$d1));
return $actions;
}
インデックスオン後creation_date
、notification_action
パフォーマンスが2番目に向上しました0.97
。
しかし、それはまだ製品には悪いです。データベースは適度にいっぱいではありません。今後の負担が心配です。何を指示してるんですか?簡単なトリックで調整できますか?それとも、構造を再設計する必要がありますか?
編集:これはクエリログです。
> db.system.profile.find().limit(10).sort( { ts : -1 } ).pretty()
{
"op" : "query",
"ns" : "splive.notification_action",
"query" : {
"$query" : {
"$or" : [
{
"not_item._id" : ObjectId("51991be7a46da17941000000"),
"creation_date" : {
"$gte" : ISODate("2013-08-08T14:05:54.170Z")
}
}, ... (***778 item***)
],
"owner.id" : {
"$ne" : "1"
}
},
"$orderby" : {
"creation_date" : -1
}
},
"ntoreturn" : 0,
"ntoskip" : 0,
"nscanned" : 12226,
"keyUpdates" : 0,
"numYield" : 1,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(912990),
"w" : NumberLong(0)
},
"timeAcquiringMicros" : {
"r" : NumberLong(10239),
"w" : NumberLong(8)
}
},
"nreturned" : 0,
"responseLength" : 20,
"millis" : 902,
"ts" : ISODate("2013-08-08T15:58:39.758Z"),
"client" : "127.0.0.1",
"allUsers" : [ ],
"user" : ""
}