什么是MySQL的预编译?
一、什么是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的预编译?相关推荐
- 利用mysql的预编译机制_SQL注入笔记记录+MySQL的事务隔离级别
(一)SQL注入. 1.如何理解SQL注入? SQL注入是一种将SQL代码添加到输入参数中,传递到SQL服务器解析并执行的一种攻击手法. 2.SQL注入是如何产生的? web开发人员无法保证所有的输入 ...
- MySQL prepare预编译
MySQL prepare预编译 PREPARE语句用于预备一个语句,并指定名称statement_name,以后引用该语句: MySQL prepare语法: PREPARE statement_n ...
- 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 ...
- jdbc mysql 源码_【JDBC系列】从源码角度理解JDBC和Mysql的预编译特性
背景 最近因为工作调整的关系,都在和数据库打交道,增加了许多和JDBC亲密接触的机会,其实我们用的是Mybatis啦.知其然,知其所以然,是我们工程师童鞋们应该追求的事情,能够帮助你更好的理解这个技术 ...
- mysql 预编译_PHP中MySQL的预处理(预编译)执行方式
MySQL的预编译是指在创建数据库对象时就将指定的SQL语句编译完成,这时SQL语句已经被MySQL解析.审查,所以相对传统的执行方式(每处理一个SQL语句就要解析SQL语句.检查语法和语义),预编译 ...
- Mysql预编译动态拼接表名查询
1.实现目标,现在对deal_runnning表进行按年月分表,需要动态拼接表名查询 2.需要执行此sql .表名要动态拼接,目标sql如下,使用concat连接表名无效. SELECT id, ba ...
- 预编译语句(Prepared Statements)介绍,以MySQL为例
1. 背景 本文重点讲述MySQL中的预编译语句并从MySQL的Connector/J源码出发讲述其在Java语言中相关使用. 注意:文中的描述与结论基于MySQL 5.7.16以及Connect/J ...
- mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- php mysql 预编译语句_php mysql 预编译
预编译执行 dml 语句 //mysql预编译 $mysqli = new mysqli("localhost", "root", "root&quo ...
最新文章
- Elasticsearch索引定时清理
- 回港二次上市,会是内容社区平台的更优选吗?
- broker可以禁用吗 time_很多人会问Win8.1系统Runtime Broker是什么进程?可以禁用吗?带着这两个问题...
- TIBCO Rendezvous — 技术介绍
- HDU - 6118 度度熊的交易计划(最大费用可行流)
- 皮卡丘为什么不进化_精灵宝可梦:进化后反而变弱的精灵!皮卡丘:知道我为什么不进化了?反而会变弱!...
- 通过福禄克测试仪进行数据中心机房各个区域的测试或认证
- Android线程机制——AsyncTask
- curl post https_Fiddler抓包13fiddler 抓包导出 curl 命令行
- 总结一下安装linux系统经验-版本选择-安装ubuntu
- 数据港:专业数据中心服务提供商
- 2017黑色主题 server sql_王智好美,一袭黑色亮片吊带长裙,造型简约大气,时尚优雅...
- POJ 1753 Flip Game 简单BFS
- 【react】 react 中 前后端数据的交互方式 (原生的ajax、jq的ajax、axios、fetch )...
- Excel中计算年龄的函数
- 输入时(hour)、分(minute)、秒(second)的一个具体时间,要求打印出它的下一秒出来(一天24小时)。 例如输入的是23时59分59秒,则输出00:00:00
- mysql 登录指定sock路径
- 低代码搭建门店管理之收发货管理系统
- [转]有关FMS(FCS)设置
- 读论文-基于循环gan特征增强的夜间车辆检测 Feature Enhancement Based on CycleGAN forNighttime Vehicle Detection
热门文章
- 二维数组vector 限定大小
- 愤世嫉俗的程序员,总在某乎发表言论,当起了“键盘侠”
- 微信公众号自定义菜单失效,无法设置的解决方法
- python中参数是什么_python中parameter是什么
- [待续]联想ThinkPadE420升级之路:英睿达(Crucial)MX500+XP开启AHCI模式+64位win10
- 使用IMP导入数据时遇到ORA-20005的错误
- Python廖雪峰教程学习笔记:Day5
- ROIpooling是什么
- CG插画培训班有哪些
- 【JAVA - ArrayList】炸金花的模拟实现流程(买牌,洗牌,发牌)