我有一个产品,它部分使用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
。任何用户创建通知操作也会订阅该通知项以收听进一步的通知。
无论如何到目前为止文件大小都是计数;
notification_items = 4348
notification_subscription = 11324
和
notification_action = 12226
如果我想在notification_action上查询订阅了大多数notification_items查询的用户运行得那么慢,问题就开始了。
假设用户订阅了
的数量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
的性能指数提升至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" : ""
}