0

我有一个产品,它部分使用 mongo db 作为通知的存储。它已经运行了将近两个月,我们正面临严重的性能问题。让我介绍一下我们为通知问题设计的结构;

共有三个基本集合。

notification_item, notification_subscriptions and notification_actions

系统上所有用户创建的数据都会创建一个notification_item其中包括ownercreation_date其他一些meta data

然后数据的所有者(在第一步创建)notification_item通过notification_subscription收集订阅该数据。 notification_subscriptionnotification_item's object id(引用notification_item集合)和user_id订阅者组成。

最后是notification_action收藏。插入对任何通知项的任何操作都很简单。它的结构notification_item's object idcreation_dateother 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_datenotification_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" : ""
}
4

0 回答 0