J2EE性能优化(二)数据库

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-commit
connection.setAutoCommit(false);
// Create a prepared statement
String sql = "INSERT INTO my_table VALUES(?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
// Insert 10 rows of data
for (int i=0; i<10; i++) {
pstmt.setString(1, ""+i);
pstmt.addBatch();
}
// Execute the batch
int [] 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
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值