经过本人实测,采用预处理,性能提升大约接近10%。
关于预处理的介绍,网上资料很多,总体关心优点有如下:
预处理优点
预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行);
绑定参数减少了服务器带宽,只需发送查询的参数,而不是整个语句;
预处理语句针对 SQL 注入是非常有用的,因为参数值发送后使用不同的协议,保证了数据的合法性。
测试代码:
package main
import (
_ "github.com/go-sql-driver/mysql"
"fmt"
"database/sql"
"time"
"flag"
"math/rand"
)
const (
USERNAME = "root"
PASSWORD = "123456"
NETWORK = "tcp"
SERVER = "localhost"
PORT = 3306
DATABASE = "code369_account"
)
type Account struct {
ID uint64 `gorm:"AUTO_INCREMENT" redis:"id"` // 内部唯一ID, 自增
Account string `gorm:"size:32;unique" redis:"account"`
Password string `gorm:"size:16" redis:"password"`
Uid int64 `redis:"uid"`// 对应User表ID
}
var runtime int
func main() {
flag.IntVar(&runtime, "i", 10000, "run time")
flag.Parse()
dsn := fmt.Sprintf("%s:%s@%s(%s:%d)/%s",USERNAME,PASSWORD,NETWORK,SERVER,PORT,DATABASE)
DB,err := sql.Open("mysql",dsn)
if err != nil{
fmt.Printf("Open mysql failed,err:%v\n",err)
return
}
prepareQueryTest1(DB)
sqlQueryTest(DB)
}
func sqlQueryTest(db *sql.DB) {
sqlStr := "SELECT id, account, password FROM accounts WHERE id = %d"
t1:=time.Now()
var u Account
for k:=0;k<runtime;k++{
id := rand.Int()%10000
sql := fmt.Sprintf(sqlStr, id)
rows,err := db.Query(sql)
if err != nil {
panic(err)
}
if rows.Next(){
err := rows.Scan(&u.ID, &u.Account, &u.Password)
if err != nil {
fmt.Printf("scan data failed, err:%v\n", err)
return
}
}
rows.Close()
}
fmt.Printf("no prepare use time:%v\n", time.Since(t1))
}
// 预处理查询数据
func prepareQueryTest1(db *sql.DB) {
// 生成一条预处理
sqlStr := "SELECT id, account, password FROM accounts WHERE id = ?"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare sql failed, err:%v\n", err)
return
}
defer stmt.Close()
t1:=time.Now()
var u Account
for k:=0;k<runtime;k++{
id := rand.Int()%10000
rows, err := stmt.Query(id)
if err != nil {
fmt.Printf("exec failed, err:%v\n", err)
return
}
if rows.Next(){
err := rows.Scan(&u.ID, &u.Account, &u.Password)
if err != nil {
fmt.Printf("scan data failed, err:%v\n", err)
return
}
}
rows.Close()
}
fmt.Printf("prepare use time:%v\n", time.Since(t1))
}
测试结果:
PS E:\test\mysqlprepare> .\test.exe -i=100000
prepare use time:13.427s
no prepare use time:14.3949989s
PS E:\test\mysqlprepare> .\test.exe -i=100000
prepare use time:13.3870121s
no prepare use time:14.3995305s
PS E:\test\mysqlprepare> .\test.exe -i=100000
prepare use time:13.0820097s
no prepare use time:14.1290266s
PS E:\test\mysqlprepare>
接近10%的提升,对于数据库QPS要求比较高的项目,可以采用。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。