一:Prepere Statement 简介

 prepare statement 即 SQL 预处理。什么是 SQL 预处理? 普通 SQL 语句执行的逻辑 需要经过 server 层 的 分析器 (图中圈住的部分) 对 sql 语句进行词法语法解析、sql 编译,

这需要一些性能开销,尤其在一些高并发的场景中可能是性能提升的一个突破点。Prepere Statement 就是干这个事的,他可以对 SQL 进行预编译。 查看 MySQL 官方文档,

有这么一条说明:

Prepere Statement 适用的场景是,SQL 语句 未发生改变,只是 query 的值发生了改变的情况。通俗的讲就是,比如 有这么一条 SQL insert into t1(name, age) values ( "siri", 18 )

当你要批量执行时,Prepare 方法 可以用 占位符的方式填充 SQL 值变化的部分,即 insert into t1(name, age) values ( ?, ? ) ,可以由 Prepare 提交给 分析器预编译。下次再

执行的时候,直接 EXECUTE Statement 占位符填充,省去了再次 语法解析、编译的过程,达到一次编译,多次运行的效果。

那么,Prepere 在高并场景下,性能能提升多少呢,官方并未给出答案,下面准备实测一下:

二:Prepere Statement 性能测试

测试环境:(测试 批量 插入性能 )

  • 测试实例:MySQl 5,7
  • 配置: 4 核 8G

网上关于 prepare 性能测试的帖子很少, 于是需要自己写测试工具。( http://gitlab.xxxxx.com/master/mysql_prepare_test

工具关键部分如下:

// Prepare SQL syntax
func PrepareExec(n int, wg *sync.WaitGroup) {
// NameExec sqlStr := "insert into user(name,age) values(?,?)" // 占位符
stmt, _ := db.Prepare(sqlStr) // 开启 Prepare ,预编译 SQL 语句 defer stmt.Close()
defer wg.Done() for i := 0; i <= n; i++ {
name := RandString(10)
_, err := stmt.Exec(name, 20)
if err != nil {
fmt.Println(err)
}
//rows, _ := ret.RowsAffected() //record := fmt.Sprintf("RowsAffected: %d", rows)
//logger.Write(record)
}
} // NonPrepare SQL syntax
func NonPrepareExec(n int, wg *sync.WaitGroup) {
// NameExec
defer wg.Done()
for i := 0; i <= n; i++ {
name := RandString(8)
sqlStr := "insert into user(name,age) values(?,?)"
_, err := db.Exec(sqlStr, name, 18) // 未 prepare 处理的普通 SQL
if err != nil {
fmt.Println(err)
} //rows, _ := ret.RowsAffected()
//record := fmt.Sprintf("RowsAffected: %d", rows)
//logger.Write(record)
}
}

测试结果如下:

  • 4 个线程,每个线程 100 个 insert:
未使用 prepare:
./prepare_test --prepare=false --t=4 --i=100
cost time:409.5343ms 使用 prepare:
./prepare_test --prepare=true --t=4 --i=100
cost time:275.1861ms
  • 4 个线程,每个线程 300 个 insert:
未使用 prepare:
./prepare_test --prepare=false --t=4 --i=300
cost time:1.4089236s 使用 prepare:
./prepare_test --prepare=true --t=4 --i=300
cost time:791.6015ms

篇幅有限:测试汇总如下

  • --t thread : 线程数
  • --i insert : 每个线程 insert 语句总数
并发参数 未使用 Prepare 使用 Prepare 性能提升
t=4 i=100 409.5343ms 275.1861ms 32%
t=4 i=300 1.4089236s 791.6015ms 42%
t=4 i=500 2.1703388s 1.129176s 47%
t=8 i=100 629.015ms 297.4847ms 52%
t=8 i=300 3.2628256s 1.67031s 50%
t=8 i=500 3.2897162s 3.2978884s 0%

从测试结果看,使用 Prepare 进行 批量插入,和 普通的 sql 相比,性能提升在 30%-50% 之间,但是当超出 实例性能时用不用 Prepare 没有什么变化。

排除 其他干扰因素,保守估计 Prepare 批量插入时性能会提升在 20% - 40% 之间,这个变化还是比较明显的。

三:总结

  1. Prepere 的使用场景是,SQL 语句 未发生改变,只是 query 的值发生了改变的情况。尤其是高并发 批量 SQL 的场景。
  2. Prepere 在批量 插入时 性能提升在 20% - 40%。 但是 select / update 有待测试,感兴趣的同学可以测一下。
  3. 当 并发 达到 实例性能上限时,Prepare SQL 和 普通 SQL 的 性能没有明显变化。
  4. MySQL 5.6 版本开始支持 Prepere 预处理



    参考文档:

    https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html

原创系列,转载请注明出处,谢谢!

Prepared SQL 性能测试的更多相关文章

  1. 发现美的眼睛 Prepared SQL Statement

    DROP PROCEDURE IF EXISTS truncate_insert_sales_rank_toparow_month; DELIMITER /w/ CREATE PROCEDURE tr ...

  2. MySQL的SQL预处理(Prepared)

    Prepared SQL Statement:SQL的执行.预编译处理语法.注意点 一.SQL 语句的执行处理1.即时 SQL 一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下: 1. ...

  3. JDBC与Hibernate中SQL语句参数设置的顺序问题

    JDBC中:设置从1开始 例: Connection con = DriverManager.getConnection("jdbc:mysql://localhost/...", ...

  4. SQL Server中关于跟踪(Trace)那点事

    前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案. 简 ...

  5. 直接放个DB2 SQL STATEMENT大全好了!

    SQL statements   This topic contains tables that list the SQL statements classified by type. SQL sch ...

  6. 【转】SQL Server中关于跟踪(Trace)那点事

    前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案. 简 ...

  7. SQL Server里强制参数化的痛苦

    几天前,我写了篇SQL Server里简单参数化的痛苦.今天我想继续这个话题,谈下SQL Server里强制参数化(Forced Parameterization). 强制参数化(Forced Par ...

  8. 五、SQL映射的XML文件

    MyBatis真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL映射的XML文件是相当的简单.当然如果你将它们和对等功能的JDBC代码来比较,你会发现映射文件节省了大约95%的代码 ...

  9. SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events

    由于工作需要,决定深入研究SQL Server的扩展事件(Extended Events/xEvents),经过资料搜索,发现国外大牛的系列文章,作为“学习”阶段,我先翻译这系列文章,后续在工作中的心 ...

随机推荐

  1. MySQL 数据库SQL语句——高阶版本1

    MySQL 数据库SQL语句--高阶版本 实验准备,数据表配置 mysql -uroot -p show databases; create database train_ticket; use tr ...

  2. OpenHarmony移植:如何适配utils子系统之KV存储部件

    摘要:本文介绍移植开发板时如何适配utils子系统之KV存储部件,并介绍相关的运行机制原理. 本文分享自华为云社区<OpenHarmony移植案例与原理 - utils子系统之KV存储部件> ...

  3. springboot整合mybatisplus使用记录

    1. springboot项目基本配置 springboot基本pom依赖 <parent> <groupId>org.springframework.boot</gro ...

  4. Ansible部署K8s集群

    目录 检查网络:k8s-check.yaml 连接配置:k8s-conn-cfg.yaml 配置k8s集群dns解析: k8s-hosts-cfg.yaml 配置yum源:k8s-yum-cfg.ya ...

  5. 蓝桥杯2022年java试题

    一:基础练习: (本文只附代码,解析后续修改后添上) 1.a+b问题: 代码如下: 1 import java.util.*; 2 public class Main { 3 public stati ...

  6. 【信而泰】网络损伤仿真,为5G应用保驾护航

    5G,绝对是今年最热门的话题!2019年6月6日,工信部正式向中国电信.中国移动.中国联通.中国广电发放5G商用牌照,中国正式进入5G商用元年.5G不仅仅是一次通信技术的升级,更是开启了一个新的时代. ...

  7. 学习Spring5必知必会(6)~Spring DAO

    一.Spring 对持久层技术的支持 Spring DAO 1.模板类: 2.基类: 二.spring JDBC [JDBCTemplate 模板类] 1.案例:使用jdbc 完成crud操作 (1) ...

  8. 2021年国内外五大BI厂商_商业智能工具推荐

    ​每家公司对于BI工具的使用都有自己的特点和期望,所以当面对国内外那么多的BI厂商时,大家可能会觉得难以选择.今天我将会为大家介绍国内外五大BI厂商,对于它们做出一些分析,让大家更了解这些BI厂商. ...

  9. 【windows 操作系统】并发

    并发 在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行.其中两种并发关系分别是同步和互斥 微观角度 所有的并发处理都有排队等候,唤醒,执行等 ...

  10. Oracle表的约束

    表的约束定义:表的约束是 ORACLE 数据库中应用在表数据上的一系列强制性规则 按照约束用途分类: PRIMARY KEY:主键约束 FOREIGN KEY:外键约束 CHECK:检查约束 UNIQ ...