douxiegan6468 2017-06-15 08:53
浏览 434
已采纳

Golang上每次全局数据库连接与每次打开连接之间的性能差异

In my current project I was opening a new database connection every time when user makes request. For example:

func login(w http.ResponseWriter, r *http.Request) {

...

db, err := sqlx.Connect("postgres", "user=postgres password=*** dbname=postgres")

if err != nil {
    ErrorWithJSON(w, err.Error(), http.StatusBadRequest)
    return
}

db.SetMaxIdleConns(0)
db.SetConnMaxLifetime(time.Second * 30)

user, err := loginManager(db, m)

...

err = db.Close()

}

When I searched for other people's code, I've seen that most of the developers create a global variable for database connection, set it on the main and use this variable on entire project.

I was wondering is there any difference between these approaches? If I use global variable will there be any latency when 5 different users makes requests for register/login etc. If there will be latency, should I create multiple database connections and store them in a slice for future requests so I can pick randomly when users make request. Like a simple load balancer, I don't know?

Sorry for multiple questions. Thank you!

  • 写回答

1条回答 默认 最新

  • doutu6616 2017-06-15 09:37
    关注

    Yes, there might be a huge performance difference (might be several order of magnitude depending on the nature of queries you run and on system and server configuration).

    The sqlx.DB type wraps (embeds) an sql.DB type, which manages a pool of connections:

    DB is a database handle representing a pool of zero or more underlying connections. It's safe for concurrent use by multiple goroutines.

    The sql package creates and frees connections automatically; it also maintains a free pool of idle connections. If the database has a concept of per-connection state, such state can only be reliably observed within a transaction.

    Every time you open a new connection, a lot of things have to happen in the "background": connection string has to be parsed, a TCP connection has to be estabilished, authentication / authorization must be performed, resources must be allocated at both sides (client and server) etc. These are just the main, obvious things. Even though some of these may be provided / implemented optimized, cached, there is still a significant overhead compared to having a single DB instance which might have multiple established, authenticated connections ready in a pool, waiting to be used / utilized.

    Also quoting from sql.Open():

    The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections. Thus, the Open function should be called just once. It is rarely necessary to close a DB.

    sqlx.Connect() which you used calls sqlx.Open() which is "the same as sql.Open, but returns an *sqlx.DB instead".

    So all in all, use a single, global sqlx.DB or sql.DB instance, and share / use that everywhere. It provides you automatic connection- and connection pool management. This will provide you the best performance. You may fine-tune the connection pool with the DB.SetConnMaxLifetime(), DB.SetMaxIdleConns() and DB.SetMaxOpenConns() methods.

    Idle connections (DB.SetMaxIdleConns()) are those that are not in-use currently, but sitting in the pool, waiting for someone to pick them up. You should definitely have some of these, e.g. 5 or 10 of them, or even more. DB.SetConnMaxLifetime() controls how long a new connection may be used. Once it grows older than this, it will be closed (and a new one will be opened if needed). You shouldn't change this, default behavior is never to expire connections. Basically all defaults are sensible, you should only play with them if you experience performance problems. Also, read docs of these methods to have a clear picture.

    See this similar, possible duplicate question:

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?