sql - Golang 上全局数据库连接和每次打开连接的性能差异

标签 sql performance go connection-pooling

在我当前的项目中,每次用户发出请求时,我都会打开一个新的数据库连接。例如:

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()

}

当我搜索其他人的代码时,我看到大多数开发人员为数据库连接创建一个全局变量,将其设置在 main 上并在整个项目中使用该变量。

我想知道这些方法之间有什么区别吗?如果我使用全局变量,当 5 个不同的用户发出注册/登录请求等时是否会有任何延迟。如果有延迟,我是否应该创建多个数据库连接并将它们存储在一个 slice 中以供将来请求,以便我可以在用户时随机选择提出要求。就像一个简单的负载均衡器,我不知道?

抱歉有多个问题。谢谢!

最佳答案

是的,可能会有巨大的性能差异(可能有几个数量级,具体取决于您运行的查询的性质以及系统和服务器配置)。

sqlx.DB类型包装(嵌入)一个 sql.DB类型,管理连接池:

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.

每次你打开一个新的连接,很多事情都必须在“后台”发生:必须解析连接字符串,必须建立TCP连接,必须执行身份验证/授权,必须分配资源在双方(客户端和服务器)等。这些只是主要的,显而易见的事情。尽管其中一些可以提供/实现优化、缓存,但与单个 DB 实例相比,仍然存在显着的开销,该实例可能在池中准备好多个已建立的、经过身份验证的连接,等待使用/利用。

同时引用自 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()你用过的电话sqlx.Open() “与 sql.Open 相同,但返回一个 *sqlx.DB”

总而言之,使用一个单一的全局sqlx.DBsql.DB 实例,并在任何地方共享/使用它。它为您提供自动连接和连接池管理。这将为您提供最佳性能。您可以使用 DB.SetConnMaxLifetime() 微调连接池。 , DB.SetMaxIdleConns()DB.SetMaxOpenConns()方法。

空闲连接 (DB.SetMaxIdleConns()) 是那些当前未在使用中,但坐在池中等待有人接他们的连接。你绝对应该拥有其中的一些,例如其中有 5 或 10 个,甚至更多。 DB.SetConnMaxLifetime() 控制新连接可以使用多长时间。一旦超过这个时间,它将被关闭(如果需要,将打开一个新的)。你不应该改变这个,默认行为是永不过期连接。基本上所有默认值都是合理的,只有在遇到性能问题时才应该使用它们。另外,阅读这些方法的文档以获得清晰的画面。

看到这个类似的、可能重复的问题:

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

关于sql - Golang 上全局数据库连接和每次打开连接的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44563029/

相关文章:

sql - 如何选择两列组合相同的行

sql - 如何在oracle中更新多行

mysql - 列中包含附加结果的 GROUP BY 语句

javascript - 如何将 jquery 脚本格式化为生产环境?

go - Golang big.Float的精度问题

reflection - 在golang中使用reflect打印struct指针字段类型

sql - 在 SQL Server Management Studio 中生成 SQL 脚本

performance - 有关Firebug中的网络面板的两个问题

angular - 如何提高 Angular 6.0 应用程序的速度

json.Unmarshal 返回空白结构