Go pgx高性能访问PostgreSQL数据库

184 阅读2分钟

简介

在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