一、什么是MySQL的预编译?

通常我们发送一条SQL语句给MySQL服务器时,MySQL服务器每次都需要对这条SQL语句进行校验、解析等操作。

但是有很多情况下,我们的一条SQL语句可能需要反复的执行,而SQL语句也只可能传递的参数不一样,类似于这样的SQL语句如果每次都需要进行校验、解析等操作,未免太过于浪费性能了,因此我们提出了SQL语句的预编译。

所谓预编译就是将一些灵活的参数值以占位符?的形式给代替掉,我们把参数值给抽取出来,把SQL语句进行模板化。让MySQL服务器执行相同的SQL语句时,不需要在校验、解析SQL语句上面花费重复的时间

预编译其实就是来提高我们的查询速度的,并不是大家心里想的那个"预编译"

二、 如何使用预编译?

2.1 MySQL预编译的语法

  • 准备数据:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名称',`birthday` datetime(0) NULL DEFAULT NULL COMMENT '生日',`sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',`address` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '小龙', '2019-02-27 17:47:08', '男', '南昌市西湖区');
INSERT INTO `user` VALUES (2, '小刚', '2019-03-02 15:09:37', '男', '南昌市东湖区');
INSERT INTO `user` VALUES (3, '小兰', '2019-03-04 11:34:34', '女', '南昌市青山湖区');
INSERT INTO `user` VALUES (4, '小红', '2019-03-04 12:04:06', '女', '南昌市青云谱区');
INSERT INTO `user` VALUES (5, '小丽', '2019-03-07 17:37:26', '女', '南昌市红谷滩区');
INSERT INTO `user` VALUES (6, '小明', '2019-03-08 11:44:00', '男', '南昌市新建区');
INSERT INTO `user` VALUES (7, '龙龙', '2019-04-08 11:44:00', '男', '南昌市西湖区');

  • 定义预编译SQL语句:
-- 定义一个预编译语句
prepare name from statement; prepare statement_1 from 'select * from user where id=?';
  • 设置参数值:
set @id=1;
  • 执行预编译SQL语句:
execute statement_1 using @id;

  • 释放预编译SQL语句:
deallocate prepare statement_1;

三、使用PreparedStatement进行预编译

3.1 开启查询日志

为了方便测试,我们打开MySQL的查询日志:

  • 在MySQL配置文件中的[mysqld]下增加如下配置:
# 是否开启mysql日志  0:关闭(默认值) 1:开启
general-log=1# mysql 日志的存放位置
general_log_file="D:/query.log"


2)重启MySQL服务(要以管理员身份运行):

net stop mysqlnet start mysql

3.2 开启预编译功能

PreparedStatement的预编译功能默认是关闭的,要让其生效,必须在JDBC连接的URL设置useServerPrepStmts=true,让其打开。

  • 如下所示:

jdbc:mysql://localhost:3306/mybatis?&useServerPrepStmts=true

  • 测试代码:
package com.lscl.test;
import org.junit.Test;
import java.sql.*;public class Demo01 {@Testpublic void test1() throws Exception {// 获取连接Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true", "root", "admin");String sql = "select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);ps.setInt(1, 1);// 执行查询,获取结果集ResultSet rs = ps.executeQuery();//遍历查询结果集while (rs.next()) {System.out.println(rs.getObject("id")+"---"+rs.getObject("username"));}rs.close();ps.close();}
}
  • 查看MySQL的查询日志:

我们设置的是MySQL连接参数,目的是告诉MySQL JDBC的PreparedStatement使用预编译功能(5.0.5之后的JDBC驱动版本需要手动开启,而之前的默认是开启的)

3.3 cachePrepStmts参数

当使用不同的PreparedStatement对象来执行相同的SQL语句时,还是会出现编译两次的现象,我们可以开启"预编译缓存",来实现"一次编译,到处运行"(要是同一个Connection)

开启预编译缓存:cachePrepStmts=true;

  • url连接:
    jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true&cachePrepStmts=true

  • 测试代码(没有开启缓存):

@Test
public void test1() throws Exception {// 获取连接
//        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true&cachePrepStmts=true", "root", "admin");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true", "root", "admin");String sql = "select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);ps.setInt(1, 1);// 执行查询,获取结果集ResultSet rs = ps.executeQuery();//遍历查询结果集while (rs.next()) {System.out.println(rs.getObject("id")+"---"+rs.getObject("username"));}// 关闭对象连接rs.close();ps.close();ps = connection.prepareStatement(sql);ps.setInt(1, 1);// 执行查询,获取结果集rs = ps.executeQuery();//遍历查询结果集while (rs.next()) {System.out.println(rs.getObject("id")+"---"+rs.getObject("username"));}rs.close();ps.close();}
  • 查看查询日志:

  • 开启预编译缓存测试(在url连接上加上cachePrepStmts=true):

jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true&cachePrepStmts=true

四、Statement是否具备预编译功能?

Statement不具备预编译功能

  • 测试代码:
@Test
public void test2() throws Exception {// 获取连接Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true&cachePrepStmts=true", "root", "admin");String sql = "select * from user where id = 1";Statement statement = connection.createStatement();// 执行查询,获取结果集ResultSet rs = statement.executeQuery(sql);//遍历查询结果集while (rs.next()) {System.out.println(rs.getObject("id")+"---"+rs.getObject("username"));}rs.close();statement.close();
}
  • 查看MySQL查询日志:

五、总结

1)到了这里,大家应该知道什么是预编译了,预编译是用来提升SQL语句的响应速度的,将一段SQL语句定制成模板,把灵活的参数作为占位符让我们传递进去,达到多次执行相同的SQL语句必须要重复校验、解析等操作;

2)默认的情况下,PreparedStatement是没有开启预编译的,需要我们在连接的url参数上指定useServerPrepStmts=true参数开启,并且预编译是支持"缓存"的,我们可以通过参数cachePrepStmts=true来设置;

3)statement是不支持预编译的,即使设置了useServerPrepStmts=true也不管用;


References:

https://www.iteye.com/blog/cs-css-1847772

https://blog.csdn.net/Marvel__Dead/article/details/69486947

什么是MySQL的预编译?相关推荐

  1. 利用mysql的预编译机制_SQL注入笔记记录+MySQL的事务隔离级别

    (一)SQL注入. 1.如何理解SQL注入? SQL注入是一种将SQL代码添加到输入参数中,传递到SQL服务器解析并执行的一种攻击手法. 2.SQL注入是如何产生的? web开发人员无法保证所有的输入 ...

  2. MySQL prepare预编译

    MySQL prepare预编译 PREPARE语句用于预备一个语句,并指定名称statement_name,以后引用该语句: MySQL prepare语法: PREPARE statement_n ...

  3. linux mysql编译安装mysql_【MySQL安装】Linux下安装MySQL(预编译)

    预编译方式安装MySQL 一.环境说明 操作系统:Redhat Linux 7.2 MySQL版本:5.7 安装介质:mysql-5.7.25-linux-glibc2.12-x86_64.tar.g ...

  4. jdbc mysql 源码_【JDBC系列】从源码角度理解JDBC和Mysql的预编译特性

    背景 最近因为工作调整的关系,都在和数据库打交道,增加了许多和JDBC亲密接触的机会,其实我们用的是Mybatis啦.知其然,知其所以然,是我们工程师童鞋们应该追求的事情,能够帮助你更好的理解这个技术 ...

  5. mysql 预编译_PHP中MySQL的预处理(预编译)执行方式

    MySQL的预编译是指在创建数据库对象时就将指定的SQL语句编译完成,这时SQL语句已经被MySQL解析.审查,所以相对传统的执行方式(每处理一个SQL语句就要解析SQL语句.检查语法和语义),预编译 ...

  6. Mysql预编译动态拼接表名查询

    1.实现目标,现在对deal_runnning表进行按年月分表,需要动态拼接表名查询 2.需要执行此sql .表名要动态拼接,目标sql如下,使用concat连接表名无效. SELECT id, ba ...

  7. 预编译语句(Prepared Statements)介绍,以MySQL为例

    1. 背景 本文重点讲述MySQL中的预编译语句并从MySQL的Connector/J源码出发讲述其在Java语言中相关使用. 注意:文中的描述与结论基于MySQL 5.7.16以及Connect/J ...

  8. mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译

    mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...

  9. php mysql 预编译语句_php mysql 预编译

    预编译执行 dml 语句 //mysql预编译 $mysqli = new mysqli("localhost", "root", "root&quo ...

最新文章

  1. Elasticsearch索引定时清理
  2. 回港二次上市,会是内容社区平台的更优选吗?
  3. broker可以禁用吗 time_很多人会问Win8.1系统Runtime Broker是什么进程?可以禁用吗?带着这两个问题...
  4. TIBCO Rendezvous — 技术介绍
  5. HDU - 6118 度度熊的交易计划(最大费用可行流)
  6. 皮卡丘为什么不进化_精灵宝可梦:进化后反而变弱的精灵!皮卡丘:知道我为什么不进化了?反而会变弱!...
  7. 通过福禄克测试仪进行数据中心机房各个区域的测试或认证
  8. Android线程机制——AsyncTask
  9. curl post https_Fiddler抓包13fiddler 抓包导出 curl 命令行
  10. 总结一下安装linux系统经验-版本选择-安装ubuntu
  11. 数据港:专业数据中心服务提供商
  12. 2017黑色主题 server sql_王智好美,一袭黑色亮片吊带长裙,造型简约大气,时尚优雅...
  13. POJ 1753 Flip Game 简单BFS
  14. 【react】 react 中 前后端数据的交互方式 (原生的ajax、jq的ajax、axios、fetch )...
  15. Excel中计算年龄的函数
  16. 输入时(hour)、分(minute)、秒(second)的一个具体时间,要求打印出它的下一秒出来(一天24小时)。 例如输入的是23时59分59秒,则输出00:00:00
  17. mysql 登录指定sock路径
  18. 低代码搭建门店管理之收发货管理系统
  19. [转]有关FMS(FCS)设置
  20. 读论文-基于循环gan特征增强的夜间车辆检测 Feature Enhancement Based on CycleGAN forNighttime Vehicle Detection

热门文章

  1. 二维数组vector 限定大小
  2. 愤世嫉俗的程序员,总在某乎发表言论,当起了“键盘侠”
  3. 微信公众号自定义菜单失效,无法设置的解决方法
  4. python中参数是什么_python中parameter是什么
  5. [待续]联想ThinkPadE420升级之路:英睿达(Crucial)MX500+XP开启AHCI模式+64位win10
  6. 使用IMP导入数据时遇到ORA-20005的错误
  7. Python廖雪峰教程学习笔记:Day5
  8. ROIpooling是什么
  9. CG插画培训班有哪些
  10. 【JAVA - ArrayList】炸金花的模拟实现流程(买牌,洗牌,发牌)