访问效率
范围:8i&9i的jdbc driver。
敬告:对于其他版本,想来差不多,但用时总先测测才好,这些经验也是……用时测测最好。
1、PrepareStatement 和 Statement
如果这个语句唯一,只执行一次(对所有的客户端都是唯一的,即每次执行都需要oracle解析),那么用Statement比较好,不需要额外的通信。如果这个语句会执行多次,一定要用PrepareStatement。如:
PreparedStatement preparedstatement = null;
Connection conn = null;
java.util.Properties prop = new java.util.Properties();
prop.setProperty("user", userName);
prop.setProperty("password", passwd);
Connection conn = DriverManager.getConnection(urlOfDb, prop);
conn.prepareStatement("insert into test values(?)");
preparedstatement.setString(1,"test");
2、addBatch()的理解
(1) 比单个:无区别。如果是不同的sql语句用addBatch,效率和一条条语句单独执行的效率基本上一样(我没有测出区别):
如:
Statement st = conn.createStatement();
st.addBatch("update test set s='xxx'");
st.addBatch("update test set s='yyy''");
st.executeBatch();
和
Statement st = conn.createStatement();
st.execute("update test set s='xxx'");
st.execute("update test set s='yyy''");
(2) 比单个:高效。如果是PrepareStatement,对参数的批处理,则效率相当的高,比如N(N很大)个插入的情况下,效率可以是原来的N倍上下(时间达到1/N)--当然是通常情况下,具体应用考虑网络,程序等因素。
语句如下:
conn.prepareStatement("insert into test values(?)");
for(int i=0; i<1000;i++){
preparedstatement.setString(1,"test"+i);
preparedstatement.addBatch();
}
int[] updateCounts = preparedstatement.executeBatch();
3、更新和查询(测试不深,使用时可测试一下,差别也并不大,敬请赐教)
在查询时,用execute或者executeQuery。
在更新(或者执行ddl语句)而不要返回数据时,用executeUpdate较好。
MySQL Oracle 查询第10到第100个记录等区间数据时的对比和原因探讨
由于项目的关系,需要同时支持MySQL和Oracle数据库,所以有一些小的细节,这里也写出来。本来这些都很简单,但是和程序的其他方面混在一起,就让人费时,让人头晕了。这里写的一点,其实也希望以后有更多的总结,更希望大家献出宝贵经验,指点指点。
首先是查询固定数目的记录:
查询 | MySQL | Oracle |
从第10条开始的100条 | select * from test limit 10,100 | select * from (select test.*, rownum ro from test where rownum <=100) where ro >10 |
1、rownum 是指选择出来的记录的计数,所以只能用<,<=,(即结果集每得到一条记录,rownum才+1,使用>则永远找不到记录)
2、语句
select id,name from test where rownum <=100 order by id;
会先选择出100条记录然后再排序,所以要选择按顺序排列的记录的前100个,应该使用
select * from (select id,name from test order by id) where rownum <=100;
其次,min,sum等聚集函数时,一定要在取得数据后,判断是否为NULL,否则结果是不对的:
stmt = dbCon.prepareStatement("select min(i) from test");
rs = stmt.executeQuery();
if(rs.next())
{
long k= rs.getLong(1);
if(rs.wasNull()) //需要在getLong之后判断
System.out.println("NUll!!");
}
另外,如果用到statement.getMetaData(),一定要注意,Oracle的元数据都是大写的。
大对象的问题 BLOB,CLOB,Long Raw(Oracle,MySQL)
1、ORACLE,如果要把一个二制文件存入ORACLE,用标准的JDBC你就要用LONG ROW类型(BLOB需要使用Oracle特定处理,见后)
InputStream fin = new FileInputStream(file);
PreparedStatement pstmt = con.prepareStatement("insert into tb_file values('aaa.gif',?)");
pstmt.setBinaryStream (1, fin, fileLength);
pstmt.executeUpdate();
fin.close();
记得update以后才能关闭流。
2、ORACLE,使用BLOB
con.setAutoCommit(false);
stmt.executeUpdate("insert into tb_file values('aaa.gif',empty_blob())");
下面必须SELECT得到BLOB的对象再向里写:
rs = stmt.executeQuery("select detail from tb_file where name='aaa.gif' for upfdate" );
if(rs.next())
{
Blob blob = rs.getBlob(1);
BinaryOutputStream out = ((oracle.sql.BLOB)blob).getBinaryOutputStream();
byte[] b = new byte[((oracle.sql.BLOB)blob).getBufferSize];
InputStream fin = new FileInputStream(file);
int len = 0;
while( (len = fin.read(b)) != -1)
out.write(b,0,len);
fin.close();
out.close();
con.commit();
}
如果用setBinaryInputStream对BLOB操作,大于1k左右的Byte就异常了。
同样读取数据你并不能象LONG ROW那样
InputStream in = rs.getBinaryInputStream("detail");
而要
Blob blob = rs.getBlob("detail");
in = blob.getBinaryStream();
3、MySQL
Varchar最大长度只有255,所以长了就建议用blob。MySQL的blob也奇怪,分成几种:TINYBLOB 其容量为 256 字节、 BLOB 其容量为 64KB 、 MEDIUMBLOB 其容量为 16MB 、 LONGBLOB 其容量为 4GB