813 字
4 分钟
连接池与性能优化

GORM 连接池与性能优化#

连接池#

sqlDB, err := db.DB()
if err != nil {
return err
}
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
sqlDB.SetConnMaxIdleTime(10 * time.Minute)

参数含义:

  • MaxIdleConns:空闲连接池上限。
  • MaxOpenConns:打开连接总数上限,包含使用中和空闲连接。
  • ConnMaxLifetime:连接最大复用时间。
  • ConnMaxIdleTime:连接空闲多久后回收。

调优时需要结合数据库最大连接数、应用实例数量和实际并发计算。多实例部署时,每个实例的 MaxOpenConns 会叠加到数据库总连接数。

连接池监控#

stats := sqlDB.Stats()
fmt.Printf("open=%d in_use=%d idle=%d wait_count=%d wait_duration=%s\n",
stats.OpenConnections,
stats.InUse,
stats.Idle,
stats.WaitCount,
stats.WaitDuration,
)

重点观察:

  • WaitCount、WaitDuration 持续升高:连接池不足、SQL 过慢或事务持有连接时间过长。
  • OpenConnections 接近上限:需要确认数据库容量和应用并发。
  • 连接频繁创建销毁:检查生命周期、网络和数据库端连接超时配置。

减少不必要的数据#

db.Select("id", "name", "status").
Where("status = ?", "active").
Order("id DESC").
Limit(50).
Find(&users)

列表接口不要默认 SELECT *;只扫描实际需要的字段,并设置合理的分页上限。

批量操作#

db.CreateInBatches(&events, 500)

大量数据导入时:

  • 按批次写入,避免一次性占满内存。
  • 根据数据库参数限制调整批大小。
  • 评估是否需要显式事务包裹整个批次或每个批次。
  • 保留失败批次的定位信息,支持重试或断点续传。

避免 N+1#

问题写法:

for _, user := range users {
db.Where("user_id = ?", user.ID).Find(&user.Orders)
}

优先使用预加载或一次性批量查询:

db.Preload("Orders").Find(&users)

预加载并非总是最优,要用 SQL 日志、数据量和执行计划验证。超大集合可以改成按需查询、分批查询或聚合查询。

默认事务和 prepared statement#

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
SkipDefaultTransaction: true,
PrepareStmt: true,
})

这两个选项都不是“打开就一定更快”:

  • 关闭默认事务可能减少单条写入开销,但会减少一致性保障。
  • prepared statement 适合重复 SQL,但会消耗 statement/连接资源,SQL 形状变化很大时收益有限。

先压测,再按业务边界逐项调整。

索引与执行计划#

索引应围绕真实查询设计:

  • 等值筛选字段。
  • 范围筛选字段。
  • 连接和外键字段。
  • 排序字段,必要时使用联合索引。
  • 唯一约束对应的唯一索引。

使用 GORM 生成 SQL 后,在目标数据库执行 EXPLAIN。重点看是否命中索引、扫描行数、排序、临时表和连接顺序。

分页优化#

OFFSET 在深分页时可能越来越慢:

db.Where("id < ?", lastID).
Order("id DESC").
Limit(50).
Find(&users)

游标分页需要稳定、可比较、有索引的排序键;如果按时间排序,通常需要使用 (created_at, id) 组合游标处理同一时间戳的记录。

性能排查顺序#

确认接口耗时
-> 统计 SQL 次数和慢 SQL
-> 检查是否 N+1 / 全字段 / 深分页
-> 用 EXPLAIN 看执行计划
-> 检查连接池等待和事务时长
-> 加索引或改写查询
-> 压测并比较 p95/p99

不要只根据单次本地查询耗时调整连接池;数据库、网络、数据量和并发都会改变结果。

官方资料#

连接池与性能优化
https://shirone.mysqil.com/posts/gorm/连接池与性能优化/
作者
HikariTish
发布于
2026-07-30
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取