为什么使用Golang Mongo驱动程序时一个简单的查询需要超过2秒的时间?

huangapple go评论69阅读模式
英文:

Why is a simple query taking more than 2 seconds with Golang Mongo driver?

问题

我正在编写一个使用go.mongodb.org/mongo-driver v1.11.6的Golang Web服务,其中包含一个Mongo数据库。一个简单的查询需要超过2秒才能完成。数据库中只有几条记录,仅用于测试,不超过10条记录。

我一直在查找耗时的代码部分,发现问题出在mongo包上。Find、FindOne甚至Insert和Update方法都需要超过1或2秒才能完成。

这是Mongo客户端的实例化代码:

func NewMongoDB() *MongoDB {
    uri := config.GetEnvConfig().MongoURI
    database := config.GetEnvConfig().MongoDatabase

    client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))

    if err != nil {
        panic(err)
    }

    return &MongoDB{
        client:   client,
        database: database,
    }
}

这是函数的代码:

func getMessageByIdFromDB(id string) (*Message, error) {
    conn := database.NewMongoDB()
    defer conn.Disconnect()

    filter := map[string]string{
        "message_id": id,
    }

    var message Message

    start := time.Now()

    err := conn.GetCollection(collectionName).FindOne(context.TODO(), filter).Decode(&message)

    elapsed := time.Since(start)
    log.Printf("查询消息耗时:%s", elapsed)

    if err != nil {
        return nil, err
    }

    return &message, nil
}

这是函数的时间跟踪结果:

查询消息耗时2.320409472

这不是因为网络连接的问题,因为我用Python进行了查询测试,请求只需要0.003秒。

我尝试更改包的版本,但没有成功。我还尝试重新安装项目的所有包,结果相同。

我还尝试在数据库中创建搜索索引,但结果没有任何不同。查询仍然需要超过2秒才能完成。

我认为查询不应该需要超过几毫秒才能完成。

英文:

I am coding a golang web service that has a mongo database, I am using the go.mongodb.org/mongo-driver v1.11.6 and a simple query is taking more than 2 seconds to complete. The database has only a few records, is it just for testing, no more than 10 records.

I've been looking for the code part where the time is being wasted and I found that the problem is with the mongo package. The methods Find, FindOne and even Insert and Update are taking more than 1 or 2 seconds to complete.

This is the mongo client instantiation

func NewMongoDB() *MongoDB {
    uri := config.GetEnvConfig().MongoURI
    database := config.GetEnvConfig().MongoDatabase

    client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))

    if err != nil {
	panic(err)
    }

    return &MongoDB{
	client:   client,
	database: database,
    }
}

This is the function code:

func getMessageByIdFromDB(id string) (*Message, error) {
    conn := database.NewMongoDB()
    defer conn.Disconnect()

    filter := map[string]string{
	"message_id": id,
    }

    var message Message

    start := time.Now()

    err := conn.GetCollection(collectionName).FindOne(context.TODO(), filter).Decode(&message)

    elapsed := time.Since(start)
    log.Printf("Querying messages took %s", elapsed)

    if err != nil {
	return nil, err
    }

    return &message, nil
}

This is the result of the time tracking of the function:

Querying messages took 2.320409472s

It is not about internet connection because I made the query test with python and the request took only 0.003 seconds

I tried to change the version of the package without achieving it. Also I tried to reinstall all the packages of the project, with the same result.

I also tried to create search indexes in database with no different results. The query also take more than 2 seconds to complete.

I think the query shouldn't take more than a few milliseconds to complete.

答案1

得分: 4

mongo.Connect()方法仅通过启动后台监控goroutine来初始化Client。它可能不需要连接到(远程)数据库。

当您执行查询时,它们肯定需要建立连接,这可能需要几秒钟的时间。

您可以在执行查询之前使用Client.Ping()方法来强制连接到数据库并验证连接是否成功创建,这样在之后执行查询时,连接将准备就绪。

您还可以尝试重复相同的查询,因为在第一次查询之后,连接不会关闭,而是放入连接池中,并在需要时再次重用(用于第二次查询)。

英文:

mongo.Connect() "only" initializes the Client by starting background monitoring goroutines. It may not necessary connect to the (remote) database.

When you then perform queries, they certainly require to build up connections, and that may take seconds.

You may use the Client.Ping() method prior to force connecting to the database and verify that the connection was created successfully, so when you perform queries after that, a connection will be ready.

You may also try to repeat the same query, as after the first query the connection will not be closed but put into a connection pool and reused when needed again (for the second query).

huangapple
  • 本文由 发表于 2023年5月26日 22:56:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76341966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定