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

Sql Golang上全局数据库连接和每次打开连接的性能差异,sql,performance,go,connection-pooling,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.StatusBadReques

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

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个不同的用户发出注册/登录等请求时是否会有延迟。如果会有延迟,我是否应该创建多个数据库连接并将它们存储在一个切片中以备将来的请求,以便在用户发出请求时可以随机选择。就像一个简单的负载平衡器,我不知道


对不起,有很多问题。谢谢大家!

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

该类型包装(嵌入)一个类型,该类型管理一个连接池:

DB是一个数据库句柄,表示零个或多个底层连接的池。多个goroutine同时使用它是安全的

sql包自动创建和释放连接;它还维护空闲连接的空闲池。如果数据库具有每个连接状态的概念,则只能在事务中可靠地观察到这种状态

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

还引述:

返回的数据库对于多个goroutine并发使用是安全的,并维护自己的空闲连接池因此,应该只调用一次Open函数。很少需要关闭数据库。

您使用的调用“与sql.Open相同,但返回一个*sqlx.DB”

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

空闲连接(
DB.setmaxidlecons()
)是那些当前未使用的连接,但它们位于池中,等待有人接它们。你肯定应该有一些,例如5个或10个,甚至更多
DB.SetConnMaxLifetime()
控制新连接的使用时间。一旦它变得比这个更老,它将被关闭(如果需要,一个新的将被打开)。您不应该更改此设置,默认行为是永不使连接过期。基本上,所有默认值都是合理的,只有在遇到性能问题时才应该使用它们。同时,阅读这些方法的文档以获得清晰的图像

请参阅类似的、可能重复的问题:


谢谢您的回答:)我是一名自学成才的golang开发者,或者试图成为。。。所以有时候我真的很难找到答案。你能分享一下你对我的负载/平衡器想法的看法吗?它是必要的还是提高了我的代码的性能?@MertSerin认为“负载平衡器”的概念是“不成熟的”,而
sql.DB
提供了一种开箱即用的、甚至更复杂、更高效的变体,即可以配置/微调的连接池。见编辑后的答案。您只需要一个
sqlx.DB
sql.DB
,再次感谢。最后一个问题,我是否应该使用这些代码行“db.setMaxIdlecons(0)”和“db.SetConnMaxLifetime(time.Second*30)”@MertSerin再次查看编辑过的答案。总而言之,默认值基本上是好的,只有在出现性能问题时才应该更改它们。