我有一个产品,它部分使用 mongo db 作为通知的存储。它已经运行了将近两个月,我们正面临严重的性能问题。让我介绍一下我们为通知问题设计的结构;
共有三个基本集合。
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;
}
在 index oncreation_date
的notification_action
性能提高到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" : ""
}