J2EE性能优化(二)数据库

来源:互联网 发布:多益网络试用期被辞退 编辑:程序博客网 时间:2024/04/27 21:04
1、保证SQL返回的数据不超出内存限度

  需要保证进行查询时的条件不会失效,如下代码就有可能出现查询条件失效的情况:

// 已经获取到 Connection;String sql=" SELECT FILED1, FIELD2 FROM SOME_TABLE WHERE NAME LIKE ?";PreparedStatement ps=conn.prepareStatement(sql);//其中 condition 为传入的查询条件ps.setString(1,"%"+condition);

  当 condition 为 "" 时会导致查询出 表 SOME_TABLE 中的所有数据。说明:利用 SQL 语句查询返回的数据量很大的情况下,容易出现 GC 恶性循环的情况。比如,我们一次性从数据库中查出了 100 万条数据,当我们在内存中存储了 90 万条后内存资源紧张, 开始进行 GC。 由于内存中大部分对象都是活动的, 结果只回收了很少的资源 (由于没有完成 JDBC 跟数据库的交互,所有的 JDBC 资源将无法释放) ,程序仍然从数据库中取得后续数据。此时会导致 GC 的不断进行,加剧资源的紧张,同时导致系统响应变慢并最终导致OOM。此时观察 JVM 会发现 JVM 在不断的努力进行 GC 的动作,但是每次都几乎回收不到空间。


2、显式获取各列,不要 SELECT *

  建议显式获取列,即使是所有字段也应罗列。不好的代码:

SELECT * FROM SOME_TABLE


  应该改写为:SELECT FIELD1 , FIELD2 , FIELD3 FROM SOME_TABLE

  依次关闭 JDBC 资源:ResultSet、PreparedStatement、Connection。在程序的 finally 中按照推荐的顺序依次关闭 JDBC 资源,如下:

Connection conn = null;ResultSet rs = null;PreparedStatement ps = null;try{// 执行数据库操作}catch(SomeException e){// 对异常进行处理;}finally{// 依次释放资源if (rs != null)try{ rs.close();} catch(Exception e){e.printStackTrace();}if (ps != null)try{ ps.close();} catch(Exception e){e.printStackTrace();}if (conn != null)try{ con.close();} catch(Exception e){e.printStackTrace();}}

3、避免DAO调用DAO
  如果 DAO 方法内会获取连接,应该避免 DAO 调用 DAO,因为这样同一个线程就会占用多个 Connection。


4、用CodeTable缓存只读数据,减少访问数据库次数
  应用系统如果要频繁访问数据库的只读数据,可以用 CodeTable 缓存这些数据,减少对数据库的访问。用于缓存的 CodeTable 可以采用 Lazy Initialization 的方式进行初始化。


5、使用存储过程优化复杂的数据库操作
  当有复杂数据操作,或者一个操作涉及多个 SQL 语句的时候,可以考虑使用存储过程来优化数据库操作。

6、批量更新一批数据
  当一个操作需要更新一批数据的时候,采用批量更新,减少和数据库的交互次数。例如下面的代码:

try {// Disable auto-commitconnection.setAutoCommit(false);// Create a prepared statementString sql = "INSERT INTO my_table VALUES(?)";PreparedStatement pstmt = connection.prepareStatement(sql);// Insert 10 rows of datafor (int i=0; i<10; i++) {pstmt.setString(1, ""+i);pstmt.addBatch();}// Execute the batchint [] updateCounts = pstmt.executeBatch();connection.commit();} catch (SQLException e) {connection.rollback();}

  可以使用下边方法判断一个数据库是否支持批量处理:

try {DatabaseMetaData dmd = connection.getMetaData();if (dmd.supportsBatchUpdates()) {// Batching is supported} else {// Batching is not supported}} catch (SQLException e) {// Handle the exception}


0 0