MySQL的预编译功能

预编译的好处

大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能。什么是预编译功能呢?它有什么好处呢?

当客户发送一条SQL语句给服务器后,服务器总是需要校验SQL语句的语法格式是否正确,然后把SQL语句编译成可执行的函数,最后才是执行SQL语句。其中校验语法,和编译所花的时间可能比执行SQL语句花的时间还要多。

如果我们需要执行多次insert语句,但只是每次插入的值不同,MySQL服务器也是需要每次都去校验SQL语句的语法格式,以及编译,这就浪费了太多的时间。如果使用预编译功能,那么只对SQL语句进行一次语法校验和编译,所以效率要高。

 

MySQL执行预编译

MySQL执行预编译分为如三步:

  • 执行预编译语句,例如:prepare myfun from 'select * from t_book where bid=?'
  • 设置变量,例如:set @str='b1'
  • 执行语句,例如:execute myfun using @str

 

如果需要再次执行myfun,那么就不再需要第一步,即不需要再编译语句了:

  • 设置变量,例如:set @str='b2'
  • 执行语句,例如:execute myfun using @str

 

通过查看MySQL日志可以看到执行的过程:

 

使用Statement执行预编译

使用Statement执行预编译就是把上面的SQL语句执行一次。

        Connection con = JdbcUtils.getConnection();

        Statement stmt = con.createStatement();

        stmt.executeUpdate("prepare myfun from 'select * from t_book where bid=?'");

        stmt.executeUpdate("set @str='b1'");

        ResultSet rs = stmt.executeQuery("execute myfun using @str");

        while(rs.next()) {

            System.out.print(rs.getString(1) + ", ");

            System.out.print(rs.getString(2) + ", ");

            System.out.print(rs.getString(3) + ", ");

            System.out.println(rs.getString(4));

        }

        

        stmt.executeUpdate("set @str='b2'");

        rs = stmt.executeQuery("execute myfun using @str");

        

        while(rs.next()) {

            System.out.print(rs.getString(1) + ", ");

            System.out.print(rs.getString(2) + ", ");

            System.out.print(rs.getString(3) + ", ");

            System.out.println(rs.getString(4));

        }

        

        rs.close();

        stmt.close();

        con.close();

 

useServerPrepStmts参数

默认使用PreparedStatement是不能执行预编译的,这需要在url中给出useServerPrepStmts=true参数(MySQL Server 4.1之前的版本是不支持预编译的,而Connector/J在5.0.5以后的版本,默认是没有开启预编译功能的)。

例如:jdbc:mysql://localhost:3306/test?useServerPrepStmts=true

  这样才能保证mysql驱动会先把SQL语句发送给服务器进行预编译,然后在执行executeQuery()时只是把参数发送给服务器。

        Connection con = JdbcUtils.getConnection();

        String sql = "select * from t_book where bid=?";

        PreparedStatement pstmt = con.prepareStatement(sql);

        

        pstmt.setString(1, "b1");

        ResultSet rs = pstmt.executeQuery();

        while(rs.next()) {

            System.out.print(rs.getString(1) + ", ");

            System.out.print(rs.getString(2) + ", ");

            System.out.print(rs.getString(3) + ", ");

            System.out.println(rs.getString(4));

        }

        

        pstmt.setString(1, "b2");

        rs = pstmt.executeQuery();

        while(rs.next()) {

            System.out.print(rs.getString(1) + ", ");

            System.out.print(rs.getString(2) + ", ");

            System.out.print(rs.getString(3) + ", ");

            System.out.println(rs.getString(4));

        }

        

        rs.close();

        pstmt.close();

        con.close();

 

cachePrepStmts参数

当使用不同的PreparedStatement对象来执行相同的SQL语句时,还是会出现编译两次的现象,这是因为驱动没有缓存编译后的函数key,导致二次编译。如果希望缓存编译后函数的key,那么就要设置cachePrepStmts参数为true。例如:

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

 

        Connection con = JdbcUtils.getConnection();

        String sql = "select * from t_book where bid=?";

        PreparedStatement pstmt = con.prepareStatement(sql);

        

        pstmt.setString(1, "b1");

        ResultSet rs = pstmt.executeQuery();

        while(rs.next()) {

            System.out.print(rs.getString(1) + ", ");

            System.out.print(rs.getString(2) + ", ");

            System.out.print(rs.getString(3) + ", ");

            System.out.println(rs.getString(4));

        }

        

        pstmt = con.prepareStatement(sql);

        pstmt.setString(1, "b2");

        rs = pstmt.executeQuery();

        while(rs.next()) {

            System.out.print(rs.getString(1) + ", ");

            System.out.print(rs.getString(2) + ", ");

            System.out.print(rs.getString(3) + ", ");

            System.out.println(rs.getString(4));

        }

        

        rs.close();

        pstmt.close();

        con.close();

 

打开批处理

MySQL的批处理也需要通过参数来打开:rewriteBatchedStatements=true

 

 

Mysql的预编译和批处理的更多相关文章

  1. MySQL的预编译功能

      1.预编译的好处 大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能.什么是预编译功能呢?它有什么好处呢? 当客户发送一条SQL语句给服务器后,服务器总是需要校验S ...

  2. MySQL开启预编译环境

    Mysql是默认 没有开启预编译的,需要在配置中加上 jdbc:mysql://xxx.22.11.31:3306/dbname?useServerPrepStmts=true

  3. php mysql语句预编译(preparestatement)

    预处理语句用于执行多个相同的 SQL 语句,并且执行效率更高. 预处理语句的工作原理如下: 预处理:创建 SQL 语句模板并发送到数据库.预留的值使用参数 "?" 标记 .例如: ...

  4. 浅谈 MySQL的预编译

    之前的一篇 Mybatis中 #{}和${}的区别 中涉及到通过 SQL预编译和 #{} 传值 的方式防止SQL注入. 由此引发了想了解预编译的想法.那么什么是预编译那? 一.三个阶段: 词法和语义解 ...

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

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

  6. mysql预编译

    一.背景: 用Mybatis+mysql的架构做开发,大家都知道,Mybatis内置参数,形如#{xxx}的,均采用了sql预编译的形式,举例如下: <select id=”aaa” param ...

  7. CentOS下MySQL 5.7编译安装

    CentOS下MySQL 5.7编译安装   文章目录 安装依赖包 下载相应源码包 添加mysql用户 预编译 编译安装 启动脚本,设置开机自启动 /etc/my.cnf,仅供参考 初始化数据库 设置 ...

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

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

  9. mybatis之 # 与 $ 区别以及 sql 预编译

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

随机推荐

  1. 添加安全认证的webservice

    添加个Key类继承SoapHeader public class KEY : SoapHeader{    public KEY()    {        //        //TODO: 在此处 ...

  2. 最佳编程字体:M+

    英文原文:The Best Font for Programming: M+ 程序员的最佳等宽字体是 M+. 一个偶然机会遇到了这个字体,在命运多舛的  kod 编辑器体验了.这个字体非比寻常,我坚持 ...

  3. asp.net Mvc 模型绑定项目过多会导致页面运行时间卡

    asp.net Mvc 模型绑定项目过多会导致页面运行时间卡的问题. 解决方式就是采用ModelView方式进行精简,已减少模型绑定及验证的时间.

  4. ionic xcode8 App上传应用详细流程

    第一步: 进入开发者官网 https://developer.apple.com   2.证书 序号1:开发者证书,用于真机调试   序号2:上传证书,用于发布最终版 3.证书申请 由于我现在是要发布 ...

  5. Asp.net Core 2.1 Kestrel 现在支持 多协议处理(Tcp)

    地址:https://github.com/davidfowl/MultiProtocolAspNetCore.git 在一个Kestrel服务上可以同时处理Tcp,Http,Https等多种协议. ...

  6. Map 综述(三):彻头彻尾理解 ConcurrentHashMap

    https://blog.csdn.net/justloveyou_/article/details/72783008

  7. PaaS服务之路漫谈(三)

    此文已由作者尧飘海授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Monolithic架构在产品访问量很大的情况下,有可能常会导致整个产品迭代或升级过程不能按预期进行,或者上 ...

  8. koa和egg项目webpack热更新实现

    背景 在用Node.js+Webpack构建的方式进行开发时, 我们希望能实现修改代码能实时刷新页面UI的效果. 这个特性webpack本身是支持的, 而且基于koa也有现成的koa-webpack- ...

  9. day 94 RestFramework序列化组件与视图view

    一 .复习 1. CBV流程 class BookView(View): def get(): pass def post(): pass #url(r'^books/', views.BookVie ...

  10. Comparable接口——容器中自定义类排序

    1.容器TreeMap,默认根据Key对象中某个属性的从小到大排列元素. (1)如下代码示例,Key是整型数字,所以按照其从小到大的顺序排列 public class TestTreeMap { pu ...