【问题标题】:How to improve performance while update column Clob in oracle?在 oracle 中更新列 Clob 时如何提高性能?
【发布时间】:2011-10-14 03:15:47
【问题描述】:

我用下面的代码更新oracle中的Clob列,好像没问题,工作正常,经过性能测试,报告需要消耗超过200ms,而字符串长度超过130000,有什么好处有什么办法改进吗?

  private void updateClobDetailsField(Map<Integer, String> idToDetails){
     long s1 = System.currentTimeMillis();
     Connection conn = null;
     PreparedStatement pStmt = null;
     ResultSet rset = null;
     Map<Integer, Clob> idToDetailsClob = new HashMap<Integer, Clob>();
     int BATCH_SIZE = CMType.BATCH_UPDATE_MAXSIZE;
     try
     {
         conn = getConnection();
         ServerAdapter adapter = ServerAdapter.getServerAdapter();

         List<Integer> IDList = new ArrayList<Integer>();
         for(Integer id : idToDetails.keySet()){
             IDList.add(id);
         }

         List<Integer> tempIDList = new ArrayList<Integer>(IDList);
         while(!tempIDList.isEmpty()){
              int size = tempIDList.size() < BATCH_SIZE ? tempIDList.size() : BATCH_SIZE;
              List<Integer> currentBatch = tempIDList.subList(0, size);
              String inClause = SQLHelper.prepareInClause("ID",currentBatch.size());
              pStmt = conn.prepareStatement("SELECT ID, DETAILS FROM PROGRAM_HISTORY WHERE " + inClause);
              for(int i = 0; i < currentBatch.size(); i++){
                  pStmt.setInt(i+1, (currentBatch.get(i)));
              }
              rset = pStmt.executeQuery();
              while(rset.next()){
                  int id = rset.getInt(1);
                  Clob detailsClob = rset.getClob(2);
                  Writer writer = adapter.getCharacterOutputStream(detailsClob);
                  String details = idToDetails.get(id);
                  if (details != null) {
                      writer.write(details);
                  }
                  writer.flush();
                  writer.close();
                  idToDetailsClob.put(id, detailsClob);
              }
              currentBatch.clear();
              BaseSQLHelper.close(pStmt, rset);
         }

         int counter = 0;
         pStmt = conn.prepareStatement("UPDATE PROGRAM_HISTORY SET DETAILS = ? WHERE ID = ?");

         for(int i=0; i<IDList.size(); i++){
             int index = 1;
             Clob detailsClob = (Clob) idToDetailsClob.get(IDList.get(i));
             pStmt.setClob(index++, detailsClob);
             pStmt.setInt(index++, IDList.get(i));
             pStmt.addBatch();
             counter++;
             if(counter % BATCH_SIZE == 0) {
                 pStmt.executeBatch();
                 pStmt.clearBatch();
                 counter = 0;
             }
         }
         if(IDList.size() % BATCH_SIZE > 0) {
             pStmt.executeBatch();
         }                         
     }
     catch (SQLException se)
     {
         se.printStackTrace();
     }
     catch (IOException se)
     {
         se.printStackTrace();
     }
     finally
     {
         cleanup(conn, pStmt, null);
     }
     System.out.println(System.currentTimeMillis()-s1);
}

【问题讨论】:

  • 我不知道这个 Java 在你的服务器上运行在哪里,但看起来还不错。假设一个 10Mbit 的连接,你几乎需要所有的时间来首先将这么多的数据传输到服务器。您可能有更好的联系,但要正确看待事情。

标签: java sql performance oracle jdbc


【解决方案1】:

如果我正确理解您的代码,您将文本附加到您的 details clob 列。

在 PL/SQL 中执行此操作会更快,因为您不必通过网络获取 clob。例如,您可以准备以下语句:

DECLARE
   l_details CLOB;
BEGIN
   SELECT details INTO l_details FROM program_history WHERE ID = ?;
   dbms_lob.append(l_details, ?);
END;

并绑定currentBatch.get(i)idToDetails.get(id)

请注意,您不需要使用 PL/SQL 进行额外更新。

【讨论】:

    【解决方案2】:

    使用可更新的 ResultSet 执行查询,以便在滚动浏览时更新数据,而无需执行单独的更新语句。

    您需要 create your prepared statement 并将 resultSetConcurrency 设置为 ResultSet.CONCUR_UPDATABLE。查看有关处理流的 oracle documentation,了解处理 clob 数据的各种方法。

    【讨论】:

      猜你喜欢
      • 2012-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 2018-01-16
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      相关资源
      最近更新 更多