对mongodb的低效查询

时间:2013-08-08 14:54:57

标签: performance mongodb database-design

我有一个产品,它部分使用mongo db作为通知存储。它几乎持续了两个月,我们面临严重的性能问题。 让我介绍我们为通知问题设计的结构;

有三个基本系列。

notification_item, notification_subscriptions and notification_actions

系统上所有用户创建的数据都会创建notification_item,其中包含ownercreation_date和其他meta data

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

最后是notification_action集合。对任何通知项目的任何操作都很简单。它的结构为notification_item's object idcreation_dateother 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_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" : ""
}

0 个答案:

没有答案