Performance comparison between golang sqlx and db.v3

Keywords: Programming SQL MySQL Database Windows

Recently, when communicating with a big guy, I mentioned the problem of SQL query.

His idea is to query data with the most primitive database driver without ORM. The benefits of doing so are twofold

  • Express SQL semantics clearly for later optimization. Especially in report, data analysis and other complex SQL.
  • Reduce useless encapsulation and improve program performance.

I didn't have any feelings at first. After all, ORM is friendly to programmers. It will be easier for me to use ORM, but I don't know the specific differences. So I did a simple test, using sqlx and db.v3 respectively (many people may not have heard of this DB package, which is completely personal preference).

Prepare region table jz_places with 3600 pieces of data

CREATE TABLE `jz_places` (
  `placeid` mediumint(8) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `sx` mediumint(8) unsigned NOT NULL DEFAULT '0',
  `order` mediumint(8) unsigned NOT NULL DEFAULT '0',
  `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Data creation time',
  PRIMARY KEY (`placeid`),
  KEY `name` (`name`),
  KEY `order` (`order`),
  KEY `idx_updatetime` (`updatetime`)
) ENGINE=InnoDB AUTO_INCREMENT=49987 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

sqlx code

func sqlxQuery() error {

	db, err := sqlx.Connect("mysql", "root:123456@tcp(127.0.0.1:3306)/mall?charset=utf8")
	defer db.Close()
	if err != nil {
		log.Fatalln(err)
	}
	var placesList []places
	return db.Get(&placesList, "SELECT * FROM jz_places WHERE name like ?", "Tricyclic%")

}

func BenchmarkSqlxQuery(b *testing.B) {
	b.N = 3000
	for i := 0; i < b.N; i++ {
		_ = sqlxQuery()
	}
}

db.v3 code

func dbQuery() error {
	setting := mysql.ConnectionURL{
		User:     "root",
		Password: "123456",
		Host:     "127.0.0.1",
		Database: "mall",
		Options:  map[string]string{"charset": "utf8"},
	}
	var placesList []places
	db, err := mysql.Open(setting)
	defer db.Close()
	if err != nil {
		log.Fatalln(err)
	}
	return db.Collection("jz_places").Find("name like ?", "Tricyclic%").All(&placesList)
}

func BenchmarkDBQuery(b *testing.B) {
	b.N = 3000
	for i := 0; i < b.N; i++ {
		_ = dbQuery()
	}
}

Let's look at the final result

goos: windows
goarch: amd64
pkg: mall/cmd
BenchmarkSqlxQuery-6   	    3000	   2118054 ns/op	    8850 B/op	      64 allocs/op
PASS
ok  	mall/cmd	6.695s
Success: Benchmarks passed.

goos: windows
goarch: amd64
pkg: mall/cmd
BenchmarkDBQuery-6   	    3000	   3535622 ns/op	   30020 B/op	    1054 allocs/op
PASS
ok  	mall/cmd	10.966s
Success: Benchmarks passed.

The difference between each connection query and closing is about 1ms. I think gorm and xorm will have the same situation. If you are in a high-performance scenario, using only SQL is also a good choice.

Posted by Sravan on Tue, 24 Mar 2020 07:29:38 -0700