<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
通常我們傳送一條SQL語句給MySQL伺服器時,MySQL伺服器每次都需要對這條SQL語句進行校驗、解析等操作。
但是有很多情況下,我們的一條SQL語句可能需要反覆的執行,而SQL語句也只可能傳遞的引數不一樣,類似於這樣的SQL語句如果每次都需要進行校驗、解析等操作,未免太過於浪費效能了,因此我們提出了SQL語句的預編譯。
所謂預編譯就是將一些靈活的引數值以預留位置?的形式給代替掉,我們把引數值給抽取出來,把SQL語句進行模板化。
讓MySQL伺服器執行相同的SQL語句時,不需要在校驗、解析SQL語句上面花費重複的時間
預編譯其實就是來提高我們的查詢速度的,並不是大家心裡想的那個"預編譯"
準備資料:
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;
為了方便測試,我們開啟MySQL的查詢紀錄檔:
在MySQL組態檔中的[mysqld]下增加如下設定:
# 是否開啟mysql紀錄檔 0:關閉(預設值) 1:開啟 general-log=1 # mysql 紀錄檔的存放位置 general_log_file="D:/query.log"
2)重啟MySQL服務(要以管理員身份執行):
net stop mysql net start mysql
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 { @Test public 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驅動版本需要手動開啟,而之前的預設是開啟的)
當使用不同的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不具備預編譯功能
測試程式碼:
@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
也不管用;
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45