1.使用Statement對象
2.預(yù)編譯PreparedStatement
3.使用PreparedStatement + 批處理
為了區(qū)分出這三者之間的效率,下面的事例執(zhí)行過程都是在數(shù)據(jù)庫表t1中插入1萬條記錄,并記錄出所需的時間(此時間與電腦硬件有關(guān))
1.使用Statement對象
使用范圍:當執(zhí)行相似SQL(結(jié)構(gòu)相同,具體值不同)語句的次數(shù)比較少
優(yōu)點:語法簡單
缺點:采用硬編碼效率低,安全性較差。
原理:硬編碼,每次執(zhí)行時相似SQL都會進行編譯
事例執(zhí)行過程:
public void exec(Connection conn){
try {
Long beginTime = System.currentTimeMillis();
conn.setAutoCommit(false);//設(shè)置手動提交
Statement st = conn.createStatement();
for(int i=0;i<10000;i++){
String sql="insert into t1(id) values ("+i+")";
st.executeUpdate(sql);
}
Long endTime = System.currentTimeMillis();
System.out.println("Statement用時:"+(endTime-beginTime)/1000+"秒");//計算時間
st.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
執(zhí)行時間:Statement用時:31秒
2.預(yù)編譯PreparedStatement
使用范圍:當執(zhí)行相似sql語句的次數(shù)比較多(例如用戶登陸,對表頻繁操作..)語句一樣,只是具體的值不一樣,被稱為動態(tài)SQL
優(yōu)點:語句只編譯一次,減少編譯次數(shù)。提高了安全性(阻止了SQL注入)
缺點: 執(zhí)行非相似SQL語句時,速度較慢。
原理:相似SQL只編譯一次,減少編譯次數(shù)
名詞解釋:
SQL注入:select * from user where username="張三" and password="123" or 1=1;
前面這條語句紅色部分就是利用sql注入,使得這條詞句使終都會返回一條記錄,從而降低了安全性。
事例執(zhí)行過程:
public void exec2(Connection conn){
try {
Long beginTime = System.currentTimeMillis();
conn.setAutoCommit(false);//手動提交
PreparedStatement pst = conn.prepareStatement("insert into t1(id) values (?)");
for(int i=0;i<10000;i++){
pst.setInt(1, i);
pst.execute();
}
conn.commit();
Long endTime = System.currentTimeMillis();
System.out.println("Pst用時:"+(endTime-beginTime)+"秒");//計算時間
pst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
執(zhí)行時間:Pst用時:14秒
3.使用PreparedStatement + 批處理
使用范圍:一次需要更新數(shù)據(jù)庫表多條記錄
優(yōu)點:減少和SQL引擎交互的次數(shù),再次提高效率,相似語句只編譯一次,減少編譯次數(shù)。提高了安全性(阻止了SQL注入)
缺點:
原理:
批處理: 減少和SQL引擎交互的次數(shù),一次傳遞給SQL引擎多條SQL。
名詞解釋:
PL/SQL引擎:在oracle中執(zhí)行pl/sql代碼的引擎,在執(zhí)行中發(fā)現(xiàn)標準的sql會交給sql引擎進行處理。
SQL引擎:執(zhí)行標準sql的引擎。
事例執(zhí)行過程:
public void exec3(Connection conn){
try {
conn.setAutoCommit(false);
Long beginTime = System.currentTimeMillis();
PreparedStatement pst = conn.prepareStatement("insert into t1(id) values (?)");
for(int i=1;i<=10000;i++){
pst.setInt(1, i);
pst.addBatch();//加入批處理,進行打包
if(i%1000==0){//可以設(shè)置不同的大小;如50,100,500,1000等等
pst.executeBatch();
conn.commit();
pst.clearBatch();
}
}
pst.executeBatch();
Long endTime = System.currentTimeMillis();
System.out.println("pst+batch用時:"+(endTime-beginTime)+"毫秒");
pst.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
執(zhí)行時間:pst+batch用時:485毫秒
摘自:http://www.javaeye.com/topic/368990