2016-05-31 2 views
-5

Привет, я использую следующий код для генерации CSV-файла с помощью сервлета Java, но он принимает 40 минут для создания CSV-файла без. из рядов 3000. есть ли какой-либо другой оптимизированный код, который может ускорить генерацию CSV до 1 или 2 минут. Мой код здесь:Генерация файлов CSV слишком медленная

protected void getCSVReportGererated(HttpServletRequest req, HttpServletResponse res) throws IOException{ 
     ResultSet rs = null; 
     String reportSQL = getReportSQL(); 
     PreparedStatement ps = null; 
     Connection con = DriverManager.getConnection("jdbc:derby://localhost:1527/testDb","username", "password"); 
     try{ 
      ps = conn.prepareStatement(reportSQL); 
      ps.execute(); 
      rs = ps.getResultSet(); 
      res.setContentType("text/csv"); 
      SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy-HHMM"); 
      Date dt = new Date(); 
      String reportName = "my_report"+sdf.format(dt)+".csv"; 
      res.setHeader("Content-disposition", "attachment; " + "filename=" + reportName); 
      ArrayList<String> rows = new ArrayList<String>(); 
      rows.add("col1,col2,col3,col4,col5,col6,col7,col8,col9,col10"); 
      rows.add("\n"); 
      String row = null; 
      while(rs.next()){ 
       row = String.format("%04d", Integer.parseInt(rs.getString(1)))+","+String.format("%05d", Integer.parseInt(rs.getString(2)))+","+rs.getString(3)+","+rs.getString(4)+","+rs.getString(5)+","+rs.getString(6)+","+rs.getString(7)+","+rs.getString(8)+","+rs.getString(9)+","+rs.getString(10); 
       rows.add(row); 
       rows.add("\n"); 
      } 
       Iterator<String> iter = rows.iterator(); 
       while (iter.hasNext()){ 
        String outputString = (String) iter.next(); 
        res.getOutputStream().print(outputString); 
       } 
       res.getOutputStream().flush(); 
     }catch(SQLException e){ 
      e.printStackTrace(); 
     }finally{ 
      try { 
       if (ps != null) 
        ps.close(); 
       if (conn != null) 
        conn.close(); 
       if(rs != null) 
        rs.close(); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      }  
     } 
} 
+3

Пытаться совместить обе а петли в одном. Может быть, evevn без использования «рядов» вообще. –

+2

Сколько времени потрачено на получение результатов? Рассматривали ли вы пропуски для создания «ArrayList » и напрямую записываете в выходной поток? – Filburt

+0

Использование многопоточности –

ответ

0

Попробуйте напечатать System.currentTimeInMillis(), чтобы понять, если время, затраченное на запрос дб, для первого цикла в то время как второй или во время цикла.

Вы также можете использовать только один цикл и избегать использования списка строк при печати непосредственно в выходной поток.

+0

+1, рекомендуя найти причину проблемы с производительностью. Возможно, VisualVM - еще один способ найти узкое место. – Kai

+0

Я согласен в целом; но просить «сделать профилирование» редко составляет хороший ответ. Таким образом, в этом смысле это сделало бы замечательный комментарий, но, возможно, не такой отличный ответ. – GhostCat

+0

Вы правы, я должен прокомментировать, но моя репутация все еще слишком низкая. В любом случае, если это занимает 30 минут, я полагаю, что проблема заключается в строке кода ps.execute(). – Marco

1

Вы делаете слишком много вещей одновременно. Есть по крайней мере 3 несвязанные проблемы здесь:

  1. Чтение из базы данных
  2. Преобразование в CSV
  3. обслуживающую, что CSV к HTTP конечной

Я бы разработать и протестировать эти 3 аспекта отдельно, и определить, что занимает так много времени. Ваш код может быть не самым эффективным, но похоже, что это займет 40 минут.

Если отчет вашей базы данных не является огромным, в этом случае его следует, вероятно, разделить на несколько небольших отчетов.

Во всяком случае, я бы использовать рамки MVC (Spring MVC/Spring загрузки хорошее начало) и переписать код, похожий на this answer

0

изменения Try, как это:

protected void getCSVReportGererated(HttpServletRequest req, HttpServletResponse res) throws IOException{ 
     ResultSet rs = null; 
     String reportSQL = getReportSQL(); 
     PreparedStatement ps = null; 
     Connection con = DriverManager.getConnection("jdbc:derby://localhost:1527/testDb","username", "password"); 
     try{ 
      ps = conn.prepareStatement(reportSQL); 
      ps.execute(); 
      rs = ps.getResultSet(); 
      res.setContentType("text/csv"); 
      SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy-HHMM"); 
      Date dt = new Date(); 
      String reportName = "my_report"+sdf.format(dt)+".csv"; 
      res.setHeader("Content-disposition", "attachment; " + "filename=" + reportName); 
      OutputStream stream=res.getOutputStream();   
      stream.println("col1,col2,col3,col4,col5,col6,col7,col8,col9,col10"); 

      String row = null; 
      while(rs.next()){ 
       row = String.format("%04d",rs.getInt(1)))+","+String.format("%05d", rs.getInt(2))+","+rs.getString(3)+","+rs.getString(4)+","+rs.getString(5)+","+rs.getString(6)+","+rs.getString(7)+","+rs.getString(8)+","+rs.getString(9)+","+rs.getString(10); 
       stream.println(row);     
      } 
      stream.flush(); 
     }catch(SQLException e){ 
      e.printStackTrace(); 
     }finally{ 
      try { 
       if (ps != null) 
        ps.close(); 
       if (conn != null) 
        conn.close(); 
       if(rs != null) 
        rs.close(); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      }  
     } 
} 
+0

Спасибо, я сделал это, и это ускоряет мое время до 20 минут. Большое спасибо –

+0

Добро пожаловать. Я думаю, вы должны получить еще лучшее улучшение с помощью StringBuffer для создания строки и оптимизации буфера потока. – Marco

Смежные вопросы