jdbc預編譯並排序輸出
玩Oracle的都比較關注shared pool,特別是library cache,在使用了綁定變數(預編譯sql)之後確實能得到很大的性能提升。現在在轉Mysql之後特別是innodb很多東西都還能和Oracle對得上號的,就像innodb_buffer_pool_size類似於Oracle的database buffer cache,innodb_log_buffer_size類似於redo log buffer,但是innodb_additional_mem_pool_size僅僅類似於shared pool的Data dictionary cache,似乎還缺少和library cache相對應的東西。那就有一個問題了,在Mysql裡面使用預編譯的sql還會有性能提升嗎?
這里我用java的jdbc做了一下測試,分別用Statement和PreparedStatement執行1000個sql,並運行10次
1.使用Statement做硬解析:
結果如下:
elapsed time(ms):14773
elapsed time(ms):16352
elapsed time(ms):14797
elapsed time(ms):15800
elapsed time(ms):12069
elapsed time(ms):14953
elapsed time(ms):13238
elapsed time(ms):12366
elapsed time(ms):15263
elapsed time(ms):13089
average time(ms):14270
可以看出兩種方式執行的結果幾乎相同,不像Oracle差距那麼大。而且就算是用PreparedStatement的方式,在Mysql資料庫端抓出來的sql語句也不是以變數id=?的形式出現的,而是實際的數值。後來在網上看到在連接字元串上加上useServerPrepStmts=true可以實現真正的預編譯
String url="jdbc:mysql://172.16.2.7:3306/testdb"; url=url+"?useServerPrepStmts=true";
加上這段後可以在資料庫端可以看到明確的結果:
mysql> show global status like 'Com_stmt_prepare';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| Com_stmt_prepare | 11 |
+------------------+-------+
1 row in set (0.00 sec)
但是實際的運行結果和上面幾乎一樣,性能上也沒有任何的提升。由此可以推斷出Mysql由於缺少類似於Oracle的library cache的部件,因此採用預編譯方式執行sql是沒有性能上的提升的。
『貳』 徹底搞懂JDBC的運行過程
前幾天筆者發布了博客,手寫mybatis徹底搞懂框架原理。為了幫助初學者更好理解mybatis框架,這次講解一下Java的JDBC的運行過程。
JDBC的作用
JDBC的全稱是Java DataBase Connection,也就是Java資料庫連接,我們可以用它來操作關系型資料庫。JDBC介面及相關類在java.sql包和javax.sql包里。我們可以用它來連接資料庫,執行SQL查詢,存儲過程,並處理返回的結果。
JDBC介面讓Java程序和JDBC驅動實現了松耦合,使得切換不同的資料庫變得更加簡單。
JDBC的連接步驟
執行一次JDBC連接,分六個步驟進行:
1. 導入包
在程序中包含資料庫編程所需的JDBC類。大多數情況下,使用 import java.sql.* 就足夠了
2. 注冊JDBC驅動程序
需要初始化驅動程序,這樣就可以打開與資料庫的通信。
3. 打開一個連接
使用DriverManager.getConnection()方法來創建一個Connection對象,它代表一個資料庫的物理連接。
4. 執行一個查詢
需要使用一個類型為Statement或PreparedStatement的對象(兩者區別看後文),並提交一個SQL語句到資料庫執行查詢。
5. 從結果集中提取數據
這一步中演示如何從資料庫中獲取查詢結果的數據。使用ResultSet.getXXX()方法來檢索的數據結果
6. 清理環境資源
在使用JDBC與數據交互操作資料庫中的數據後,應該明確地關閉所有的資料庫資源以減少資源的浪費。本文使用了try with resources方式關閉資源,這是JDK7的語法糖,讀者可自行搜索。
完整代碼如下。
JDBC的最佳實踐
JDBC是如何實現Java程序和JDBC驅動的松耦合?
JDBC API使用Java的反射機制來實現Java程序和JDBC驅動的松耦合。看一下上文的JDBC示例,你會發現所有操作都是通過JDBC介面完成的,而驅動只有在通過Class.forName反射機制來載入的時候才會出現。
這是Java核心庫里反射機制的最佳實踐之一,它使得應用程序和驅動程序之間進行了隔離,讓遷移資料庫的工作變得更簡單。
Statement和PreparedStatement區別
預編譯
創建時的區別:
執行時的區別:
由上可以看出,PreparedStatement有預編譯的過程,已經綁定sql,之後無論執行多少次,都不會再去進行編譯,而Statement 不同,如果執行多次,則相應的就要編譯多少次sql,所以從這點看,PreparedStatement的效率會比Statement要高一些。PreparedStatement是預編譯的,所以可以有效的防止SQL注入等問題
佔位符
PrepareStatement可以替換變數在SQL語句中可以包含?,可以用?替換成變數。
而Statement只能用字元串拼接。
JDBC的ResultSet
在查詢資料庫後會返回一個ResultSet,它就像是查詢結果集的一張數據表。
ResultSet對象維護了一個游標,指向當前的數據行。開始的時候這個游標指向的是第一行。如果調用了ResultSet的next()方法游標會下移一行,如果沒有更多的數據了,next()方法會返回false。可以在for循環中用它來遍歷數據集。
默認的ResultSet是不能更新的,游標也只能往下移。也就是說你只能從第一行到最後一行遍歷一遍。不過也可以創建可以回滾或者可更新的ResultSet,像下面這樣。
當生成ResultSet的Statement對象要關閉或者重新執行或是獲取下一個ResultSet的時候,ResultSet對象也會自動關閉。
可以通過ResultSet的getter方法,傳入列名或者從1開始的序號來獲取列數據。
ResultSet的不同類型
根據創建Statement時輸入參數的不同,會對應不同類型的ResultSet。如果你看下Connection的方法,你會發現createStatement和prepareStatement方法重載了,以支持不同的ResultSet和並發類型。
ResultSet對象有三種類型。
ResultSet有兩種並發類型。
『叄』 JDBC連接資料庫的步驟都有哪些
1、首先我們通過資料庫可視化工具navicate for mysql,新建一個資料庫,名字叫test新建一張表。