mgo - 查询性能似乎一直很慢(500-650 毫秒)

mgo - query performance seems consistently slow (500-650ms)

我的数据层大量使用 Mongo 聚合,平均而言,查询 return 需要 500-650 毫秒。我正在使用 mgo.

下面显示了一个示例查询函数,它代表了我的大部分查询的样子。

func (r userRepo) GetUserByID(id string) (User, error) {
    info, err := db.Info()
    if err != nil {
        log.Fatal(err)
    }

    session, err := mgo.Dial(info.ConnectionString())
    if err != nil {
        log.Fatal(err)
    }
    defer session.Close()

    var user User
    c := session.DB(info.Db()).C("users")
    o1 := bson.M{"$match": bson.M{"_id": id}}
    o2 := bson.M{"$project": bson.M{
        "first":           "$first",
        "last":            "$last",
        "email":           "$email",
        "fb_id":           "$fb_id",
        "groups":          "$groups",
        "fulfillments":    "$fulfillments",
        "denied_requests": "$denied_requests",
        "invites":         "$invites",
        "requests": bson.M{
            "$filter": bson.M{
                "input": "$requests",
                "as":    "item",
                "cond": bson.M{
                    "$eq": []interface{}{"$$item.active", true},
                },
            },
        },
    }}
    pipeline := []bson.M{o1, o2}
    err = c.Pipe(pipeline).One(&user)
    if err != nil {
        return user, err
    }
    return user, nil
}

我的 user 结构如下所示..

type User struct {
    ID             string        `json:"id" bson:"_id,omitempty"`
    First          string        `json:"first" bson:"first"`
    Last           string        `json:"last" bson:"last"`
    Email          string        `json:"email" bson:"email"`
    FacebookID     string        `json:"facebook_id" bson:"fb_id,omitempty"`
    Groups         []UserGroup   `json:"groups" bson:"groups"`
    Requests       []Request     `json:"requests" bson:"requests"`
    Fulfillments   []Fulfillment `json:"fulfillments" bson:"fulfillments"`
    Invites        []GroupInvite `json:"invites" bson:"invites"`
    DeniedRequests []string      `json:"denied_requests" bson:"denied_requests"`
}

根据我提供的内容,是否有任何明显的迹象表明我的查询平均耗时 500-650 毫秒?

我知道使用聚合管道可能会降低性能,但我没想到会这么糟糕。

.. is there anything obvious that would suggest why my queriers are averaging 500-650ms?

是的,有。您在执行每个查询之前调用 mgo.Dial()mgo.Dial() 每次都必须连接到 MongoDB 服务器,您在查询后立即将其关闭。建立连接很可能需要数百毫秒,包括身份验证、分配资源(在服务器端和客户端)等,这非常浪费。

This method is generally called just once for a given cluster. Further sessions to the same cluster are then established using the New or Copy methods on the obtained session. This will make them share the underlying cluster, and manage the pool of connections appropriately.

创建一个全局会话变量,在启动时连接 一次(使用例如一个包 init() 函数),并使用该会话(或它的副本/克隆) , 通过 Session.Copy() or Session.Clone()) 获得。 例如:

var session *mgo.Session
var info *db.Inf // Use your type here

func init() {
    var err error
    if info, err = db.Info(); err != nil {
        log.Fatal(err)
    }
    if session, err = mgo.Dial(info.ConnectionString()); err != nil {
        log.Fatal(err)
    }
}

func (r userRepo) GetUserByID(id string) (User, error) {
    sess := session.Clone()
    defer sess.Close()

    // Now we use sess to execute the query:
    var user User
    c := sess.DB(info.Db()).C("users")
    // Rest of the method is unchanged...
}