简介
在go的项目中,很大一部分情况都会使用gorm,但是在一个并发场景下测试发现gorm查询性能不满足,平均可能到50~100毫秒级别,导致一秒钟只能处理几十个请求,也尝试了一些gorm性能优化的特性,效果不佳。
正好因为数据库使用的是PostgreSQL,通过在瓶颈位置数据库查找替换为pgx,基本能达到毫秒级别,很好的解决了这个数据库访问的性能瓶颈。
示例
创建表
CREATE TABLE widgets (
id SERIAL PRIMARY KEY,
name VARCHAR(255),
weight INTEGER
);
插入数据
INSERT INTO widgets (name, weight) VALUES
('Widget1', 10),
('Widget2', 20),
('Widget3', 15);
pgx查询
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/jackc/pgx/v5"
)
func main() {
// urlExample := "postgres://username:password@localhost:5432/database_name"
urlExample := "postgres://postgres:postgres@127.0.0.1:5432/log_system_db"
conn, err := pgx.Connect(context.Background(), urlExample)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
defer conn.Close(context.Background())
st := time.Now()
var name string
var weight int64
err = conn.QueryRow(context.Background(), "select name, weight from widgets where id=$1", 2).Scan(&name, &weight)
if err != nil {
fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
os.Exit(1)
}
// 打印查询时间和查询结果
dt := time.Since(st)
fmt.Println("query time:", dt)
fmt.Println("name:", name, "widgets:", weight)
}
执行结果
~ # ./main
query time: 1.566621ms
name: Widget2 weight: 20
~ #
~ # ./main
query time: 4.548452ms
name: Widget2 weight: 20
~ #
~ # ./main
query time: 2.635258ms
name: Widget2 weight: 20
~ #
~ # ./main
query time: 3.477721ms
name: Widget2 weight: 20
~ #
~ # ./main
query time: 5.515165ms
name: Widget2 weight: 20
~ #
~ # ./main
query time: 1.515033ms
name: Widget2 weight: 20
~ #
总结
- 在一开始可以考虑通用数据库优化方案,包括数据库配置、表索引设计、查询sql等。
- 在性能要求不高的情况下,可以尝试gorm性能进行优化。
- 因为gorm本身是在原始数据库驱动的封装,其中的逻辑处理必然会导致性能受到部分影响。
- 条件允许的情况下,可以考虑使用原始的数据库驱动进行数据库访问操作,low-level & high performance。