前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go实测 ——Mysql 通过预处理(Prepare)提升性能

go实测 ——Mysql 通过预处理(Prepare)提升性能

原创
作者头像
IT工作者
发布2022-07-21 10:53:00
1.1K0
发布2022-07-21 10:53:00
举报
文章被收录于专栏:程序技术知识

经过本人实测,采用预处理,性能提升大约接近10%。

关于预处理的介绍,网上资料很多,总体关心优点有如下:

预处理优点

预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行);

绑定参数减少了服务器带宽,只需发送查询的参数,而不是整个语句;

预处理语句针对 SQL 注入是非常有用的,因为参数值发送后使用不同的协议,保证了数据的合法性。

测试代码:

代码语言:go
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档