您的位置:首页 > 其它

进一步提高JDBC应用程序的性能 (四)

2008-04-25 22:49 183 查看
进一步提高JDBC应用程序性能 (四)
bootcool@263.net
四:使用预编译语句和批量更新首先我们得大致的了解数据库是怎么处理各种数据库操作语句的。当数据库接收到一个语句时,数据库引擎首先解析该语句,然后分析是否有语法,语义错误。如果没有错误,数据库将计算出如何高效的执行该语句。一旦得出执行策略,就由数据库引擎执行该语句,最后把执行结果反馈给用户。虽然数据库厂商对各自的数据库做了最大的优化,但是可以想象这的确是一个开销很大的工作。于是,我们考虑如何使我们的数据库操作变得更高效呢?如果一条语句执行一次后,数据库就记录下该语句的执行策略,那么以后执行相同语句时,就可以省去上面的种种麻烦了。Java里提供了这样的接口――PreparedStatement.。通过预编译PreparedStatement 对象, 我们能够很容易的提高语句执行效率。同时,需要指出的是Java里还有另一个实现数据库操作的接口――Statement,但是当语句格式固定时我们更倾向于使用PreparedStatement,只有当语句格式无法预见时,我们才考虑采用Statement。以下是执行1000次语句结构相同的Insert,Update和Select语句的测试结果: 接口类型Insert语句Update语句Select语句第一次测试耗时第二次测试耗时第一次测试耗时第二次测试耗时第一次测试耗时第二次测试耗时Statement2360 ms2190 ms3790 ms3460 ms3570 ms2530 msPreparedStatement1270 ms1040 ms2600 ms2410 ms440 ms380 ms(表8)分析: PreparedStatement的效率明显比Statement要高出很多。另外,对于查询语句我们还得深入地看看JDBC是如何实现的。JDBC执行一次查询后,将返回一个ResultSet(结果集)。为了建立这个结果集,JDBC将对数据库访问两次。第一次要求数据库对结果集中的各列进行说明,第二次告诉数据库,当程序需要获取数据时应如何安置这些数据。由此我们能够算出执行一次或多次查询,JDBC需要访问数据库的次数。访问数据库次数 = 结果集中的列数 * 语句执行的次数 * 2 如果同样执行100次相同查询,结果集中的列数也相同时,假设为20列:使用Statement: 访问数据库次数 = 20 * 100 * 2 = 4000 使用Prepared Statement: 访问数据库次数 = 20 * 1* 2 = 400 我们还要注意一点,如果使用PreparedStatement接口的方法不当,则不能达到提高执行效率的目的。我们用一个简单的测试程序说明:import java.sql.*;
public class JDBCTEST2 {
private static Connection con = null;
private static String dbUrl = null;

public JDBCTEST2(){
}
public static void main(String args[]){
try{
dbUrl = "JDBC:odbc:test";
Class.forName("sun.JDBC.odbc.JDBCOdbcDriver");
preparedStatementInsertTest_1();
System.out.println("===================");
preparedStatementInsertTest_2();
}
catch(Exception ex){
ex.printStackTrace();
}
}

//方法1以不恰当的方式使用了PreparedStatement接口
public static void preparedStatementInsertTest_1(){
try{
con = DriverManager.getConnection(dbUrl);
PreparedStatement pst = null;
long start = System.currentTimeMillis();

//执行1000次语句结构相同的查询
for(int i=0;i<1000;i++){
pst = con.prepareStatement("select * from s where s1 = " + i);
pst.executeQuery();
pst.close();
}
System.out.println("Methord_1 Execute Ellapse:"
+(System.currentTimeMillis()-start)
+"ms");
con.close();
}
catch(Exception ex){
ex.printStackTrace();
}
}//方法2以正确的方式使用了PreparedStatement接口
public static void preparedStatementInsertTest_2(){
try{
con = DriverManager.getConnection(dbUrl);
long start = System.currentTimeMillis();
PreparedStatement pst = null;
pst = con.prepareStatement("select * from s where s1 = ?");

//执行1000次语句结构相同的查询
for(int i=0;i<1000;i++){
pst.setInt(1,i);
pst.executeQuery();
}
System.out.println("Methord_2 Execute Ellapse:"
+(System.currentTimeMillis()-start)
+"ms");
pst.close();
con.close();
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
以下是相关的测试结果:方式Select语句执行100次语句结构相同的查询耗时执行1000次语句结构相同的查询耗时第一次测试第二次测试第一次测试第二次测试方式11100 ms330 ms3510 ms3020 ms方式2110 ms 50 ms440 ms380 ms(表9) 分析:测试结果说明,如果不正确的使用了PreparedStatement接口,那么其执行效率和使用Statement没有什么差别,而PreparedStatement接口的优势也不会得到充分发挥。最后我们还得补充一点,当我们需要成批插入或者更新记录时。我们考虑采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。如果我们再配合使用PreparedStatement接口,将进一步提高程序性能。我们同样给出一个小程序予以说明。import java.sql.*;public class JDBCTEST3 { public static void main(String[] args) {
try {String[] values = {"BeiJing","KunMing"};
int[] results; Class.forName("sun.JDBC.odbc.JDBCOdbcDriver");
Connection con = DriverManager.getConnection("JDBC:odbc:test");
Statement st = con.createStatement ();
for (int i = 0; i < values.length; i++){
//把一个SQL命令加入命令列表
st.addBatch ("INSERT INTO CITY VALUES('" + values[i] + "')");
}
//执行批量更新
st.executeBatch (); PreparedStatement pst = con.prepareStatement("INSERT INTO CITY"
+"VALUES (?)");
for (int i = 0; i < values.length; i++) {
pst.setString(1, values[i]);
//把一个SQL命令加入命令列表
pst.addBatch();
}
//执行批量更新
pst.executeBatch();

st.close();
pst.close();
con.close();
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: