前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >sqlx和gorm性能对比

sqlx和gorm性能对比

原创
作者头像
Johns
修改2022-12-03 00:56:46
5.3K3
修改2022-12-03 00:56:46
举报
文章被收录于专栏:代码工具

前言

gorm(stars: 29K)是基于go开发的一个ORM工具, sqlx (stars: 12.3K)是一个基于go语言开发的, 在原生go-sql-driver/mysql(stars: 12.4K)上拓展的库.

image.png
image.png

他们是目前业界用的较多的3个组件, 故此对这几个组件进行一个简单的性能测试.

环境说明

代码语言:txt
复制
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
版本: mysql  Ver 14.14 Distrib 5.7.20, for macos10.12 (x86_64) 
数据量: 2W, 目前仅测试select查询性能, 因为这块我们使用最频繁

表定义

代码语言:sql
复制
CREATE TABLE `person` (
		`first_name` text,
		`last_name` text,
		`email` text,
		`id` int NOT NULL AUTO_INCREMENT,
		PRIMARY KEY (`id`)
	) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;

性能测试

代码语言:go
复制
package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"testing"
	"time"
)

type Person struct {
	Id        int    `db:"id"`
	FirstName string `db:"first_name"`
	LastName  string `db:"last_name"`
	Email     string `db:"email"`
}

func (p Person) TableName() string {
	return "person"
}

func Benchmark(b *testing.B) {
	dsn := fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8&parseTime=True&loc=UTC",
		"root", "362427gg", "localhost", 3306, "test")

	limits := []int{
		5,
		50,
		500,
		10000,
	}
	// 原生mysql连接池
	sqlDB, _ := sql.Open("mysql", dsn)
	sqlDB.SetMaxOpenConns(500)
	sqlDB.SetMaxIdleConns(100)

	// sqlx连接池
	sqlxDB, _ := sqlx.Connect("mysql", dsn)
	sqlxDB.SetMaxOpenConns(500)
	sqlxDB.SetMaxIdleConns(100)

	// gorm
	gormDB, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{NowFunc: func() time.Time {
		return time.Now().UTC().Round(
			time.Microsecond)
	}})
	db, _ := gormDB.DB()
	db.SetMaxOpenConns(500)
	db.SetMaxIdleConns(100)

	for _, lim := range limits {
		lim := lim

		// Benchmark origin
		b.Run(fmt.Sprintf("sql limit:%d", lim), func(b *testing.B) {
			for i := 0; i < b.N; i++ {
				q := fmt.Sprintf("SELECT id,first_name,last_name,email FROM test.person ORDER BY id LIMIT %d", lim)
				var res []Person
				rows, err := sqlDB.Query(q)
				if err != nil {
					b.Fatal(err)
				}
				defer rows.Close()
				for rows.Next() {
					p := Person{}
					rows.Scan(&p.Id, &p.FirstName, &p.LastName, &p.Email)
					res = append(res, p)
				}
			}
		})

		// Benchmark sqlx
		b.Run(fmt.Sprintf("sqlx limit:%d", lim), func(b *testing.B) {
			for i := 0; i < b.N; i++ {
				q := fmt.Sprintf("SELECT id,first_name,last_name,email FROM test.person ORDER BY id LIMIT %d", lim)
				var res []Person
				err := sqlxDB.Select(&res, q)
				if err != nil {
					b.Fatal(err)
				}
			}
		})
		// Benchmark gormDB
		b.Run(fmt.Sprintf("gormDB limit:%d", lim), func(b *testing.B) {
			for i := 0; i < b.N; i++ {
				var res []Person
				err := gormDB.Order("id").Limit(lim).Find(&res).Error
				if err != nil {
					b.Fatal(err)
				}
			}
		})

		fmt.Println("==================================================================================================================")
	}
}

测试结果

sql原生组件性能最高但是和sqlx相差10~20%, gorm的性能最差, 比原生差10~50%

代码语言:txt
复制
$  GORM_DIALECT=mysql go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: grpc-demo
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Benchmark/sql_limit:5-12                    9044            122952 ns/op            2602 B/op         63 allocs/op
Benchmark/sqlx_limit:5-12                   9093            124345 ns/op            2889 B/op         70 allocs/op
Benchmark/gormDB_limit:5-12                 8854            132475 ns/op            5646 B/op        106 allocs/op
==================================================================================================================
Benchmark/sql_limit:50-12                   5750            202876 ns/op           17971 B/op        467 allocs/op
Benchmark/sqlx_limit:50-12                  5120            219263 ns/op           19340 B/op        519 allocs/op
Benchmark/gormDB_limit:50-12                4244            262799 ns/op           21851 B/op        689 allocs/op
==================================================================================================================
Benchmark/sql_limit:500-12                  1130           1037233 ns/op          161823 B/op       4521 allocs/op
Benchmark/sqlx_limit:500-12                  964           1207199 ns/op          167845 B/op       5023 allocs/op
Benchmark/gormDB_limit:500-12                741           1569280 ns/op          187316 B/op       6543 allocs/op
==================================================================================================================
Benchmark/sql_limit:10000-12                 100          11728373 ns/op         4648238 B/op      90034 allocs/op
Benchmark/sqlx_limit:10000-12                100          12551046 ns/op         4882252 B/op     100037 allocs/op
Benchmark/gormDB_limit:10000-12               60          19835525 ns/op         5031278 B/op     130076 allocs/op
==================================================================================================================
PASS
ok      grpc-demo       14.946s

分析原因

sqlx为啥比gorm快?

(1) interface{}问题

GORM中许多函数入参的数据类型都是interface{},底层又用reflect支持了多种类型,这种实现会导致两个问题:

  • reflect导致的底层的性能不高(这点还能接受)
  • interface{}如果传入了不支持的复杂数据类型时,排查问题麻烦,往往要运行程序时才会报错

而在sqlx中测试使用的是原生的sql, 基本没有额外的反射操作.

(2) 高频拼接重复SQL

在一个程序运行过程中,执行的SQL语句都比较固定,而变化的往往是参数, 从GORM的实现来看,每次执行都需要重新拼接一次SQL语句,性能肯定也是有影响的.

而在sqlx中测试使用的是原生的sql, 只是做了个简单的字符串format操作

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 环境说明
  • 性能测试
  • 测试结果
  • 分析原因
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档