1.前言
在一个论坛上,有个朋友曾经说自己做过一个测试,通过PreparedStatement对数据库进行大批量的数据插入与不通过PrepareStatement进行插入相比,在性能上(至少在时间上)没有丝毫优越的地方——相反在一些情况下竟然不如。我几乎没有用到过PrepareStatement接口,但是看到这样的测试结果还是很令我惊讶。为了严谨起见,我们必须通过测试来证实或者证伪这样的论断。
2.PreparedStatement简介
在JDK1.4的api文档中,可以找到对PreparedStatement的描述:
AnobjectthatrepresentsaprecompiledSQLstatement.
ASQLstatementisprecompiledandstoredinaPreparedStatementobject.Thisobjectcanthenbeusedtoefficientlyexecutethisstatementmultipletimes.
根据这样的描述我们可以得到这样的印象:设计PreparedStatement是为了提高数据库处理和执行SQL语句的效率。如果起的作用是相反或者没有作用,那么就没有存在的必要。
当需要对数据库进行数据插入、更新或者删除的时候,程序会发送整个SQL语句给数据库处理和执行。数据库处理一个SQL语句,需要完成解析SQL语句、检查语法和语义以及生成代码;一般说来,处理时间要比执行语句所需要的时间长。
如果需要发送的SQL语句除了数据改变之外其他都不变——这是经常可以遇见的——假如按照通常的手段,那么数据库还是会重新解析这条语句,做上一次已经做过的事情。如果次数很多,比如上万次,那么重复解析所花费的时间就相当可观了。
PreparedStatement接口用来把一个SQL语句发送给数据库,让该语句在数据库中得到预处理,然后数据库得到程序发送过去的数据执行相应的操作。程序不断发送数据,而数据库不需要再花费解析的时间就可以执行。
3.开始测试
我们采用微软的Access2000建立一个名为db1.mdb的数据库,新建一张名为student的空表,这个表有自动递增的ID字段、name字段、physic字段、maths字段、chinese字段、english字段。
建立好数据库之后我们着手配置ODBC源,数据源名(DataSourceName)为redsun,LoginName为snow,Password为ookk。
我们通过两种途径对数据库进行10000条记录插入,第一种是利用普通的Statement接口,第二种通过PreparedStatement接口,然后通过相同的方式记录插入前后的时间差。
1)通过Statement接口:
Connectioncon;
Statementsql;
longa,b,abc;
a=0;
b=0;
abc=0;
str="INSERTINTOstudent(name,physic,maths,chinese,english)VALUES('xiaowang',90,91,93,94)";
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");}
catch(ClassNotFoundExceptione){}
try
{
con=DriverManager.getConnection("jdbc:odbc:redsun","snow","ookk");
sql=con.createStatement();
a=System.currentTimeMillis();//记录起始时间
for(inti=0;i<10000;i++)
{sql.execute(str);}
b=System.currentTimeMillis();//记录结束时间
abc=b-a;
con.close();
}
catch(SQLExceptione1){e1.getMessage();}
最后我们得到的时间差为30453毫秒。
我们将数据库中插入的数据清空,进行第二次测试。
2.通过PreparedStatment接口:
str2="INSERTINTOstudent(name,physic,maths,chinese,english)VALUES(?,?,?,?,?)";
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");}
catch(ClassNotFoundExceptione){}
try
{
con=DriverManager.getConnection("jdbc:odbc:redsun","snow","ookk");
PreparedStatementps=con.prepareStatement(str2);
ps.setString(1,"xiaowang");
ps.setInt(2,90);
ps.setInt(3,91);
ps.setInt(4,93);
ps.setInt(5,94);
a=System.currentTimeMillis();//记录起始时间
for(inti=0;i<10000;i++)
{
ps.executeUpdate();
}
b=System.currentTimeMillis();//记录结束时间
abc=b-a;
con.close();
}
catch(SQLExceptione1){e1.getMessage();}
我们得到的时间差为13429毫秒,一半的时间还不到,令人惊讶。
4.总结
我们对数据库通过两种途径插入相同的数据,所花费的时间差别是显而易见的。
在进行大批量数据的插入时——很多时候SQL语句中仅仅数据改变——PreparedStatement接口的优越性是无庸置疑的。
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>