2012-05-08 3 views
3

Моя проблема заключается в следующем: Я пытаюсь обрабатывать около 1,5 миллионов строк данных весной через JDBCTemplate, исходящие из MySQL. С таким большим количеством строк я использую класс RowCallbackHandler, как предложено hereОптимизация результата Получение производительности (Apache Spring, MySQL)

Код на самом деле работает, но SLOW ... Дело в том, что независимо от того, для чего я установил размер выборки, я, кажется, получаю приблизительно 350 записей на выборку, с задержкой от 2 до 3 секунд между выборками (от наблюдения за моими журналами). Я попробовал комментировать команду хранилища и подтвердил, что поведение оставалось неизменным, поэтому проблема не связана с записью.

Есть 6 столбцов, только 1, что является varchar, и что он имеет длину всего 25 символов, поэтому я не вижу проблемы с пропускной способностью.

В идеале я хотел бы получить больше, чем 30000-50000 строк за раз. Есть ли способ сделать это?

Вот мой код:


    protected void runCallback(String query, Map params, int fetchSize, RowCallbackHandler rch) 
      throws DatabaseException { 
     int oldFetchSize = getJdbcTemplate().getFetchSize(); 
     if (fetchSize > 0) { 
      getJdbcTemplate().setFetchSize(fetchSize); 
     } 
     try { 
      getJdbcTemplate().query(getSql(query), rch); 
     } 
     catch (DataAccessException ex) { 
      logger.error(ExceptionUtils.getStackTrace(ex)); 
      throw new DatabaseException(ex.getMessage());   
     } 
     getJdbcTemplate().setFetchSize(oldFetchSize); 
    } 

and the handler: 

public class SaveUserFolderStatesCallback implements RowCallbackHandler { 
     @Override 
     public void processRow(ResultSet rs) throws SQLException { 
      //Save each row sequentially. 
      //Do NOT call ResultSet.next() !!!! 

      Calendar asOf = Calendar.getInstance(); 
      log.info("AS OF DATE: " + asOf.getTime()); 
      Long x = (Long) rs.getLong("x"); 
      Long xx = (Long) rs.getLong("xx"); 
      String xxx = (String) rs.getString("xxx"); 
      BigDecimal xxxx = (BigDecimal)rs.getBigDecimal("xxxx"); 
      Double xxxx = (budgetAmountBD == null) ? 0.0 : budgetAmountBD.doubleValue(); 
      BigDecimal xxxxx = (BigDecimal)rs.getBigDecimal("xxxxx"); 
      Double xxxxx = (actualAmountBD == null) ? 0.0 : actualAmountBD.doubleValue();   

      dbstore(x, xx, xxx, xxxx, xxxxx, asOf); 
     }  

    } 

ответ

0

Ответ на самом деле это сделать setFetchSize (Integer.MIN_VALUE) в то время как это полностью нарушает заявленный договор Statement.setFetchSize, коннектор MySQL Java использует это значение для потоковой передачи результатов. Это приводит к огромному повышению производительности.

Еще одна часть исправления заключается в том, что мне также необходимо создать свой собственный подкласс (Spring) JdbcTemplate, который будет размещать отрицательный размер выборки ... На самом деле, я взял пример кода здесь, где я впервые нашел идею установка FetchSize (Integer.MIN_VALUE)

http://javasplitter.blogspot.com/2009/10/pimp-ma-jdbc-resultset.html

Благодарим вас за вашу помощь!

0

И что ваш запрос? Попробуйте создать indexex для полей, которые вы ищете/сортируете. Это поможет.

Вторая стратегия: реализация кэша памяти. Или использование спящего режима с кешем второго уровня.

Обе эти технологии могут значительно ускорить выполнение запроса.

+0

для # 1 просто делает отборное * на столе, так и с нет сортировки индекс не собирается помогать для # 2 смены DBS не вариант – ControlAltDel

+0

Memmory кэш не нужно от вас изменить дб – alexey28

+0

Для реализации кэша памяти у вас будет некоторая Служба с ленивой инициализацией коллекции (если вы просто выберите без какого-либо порядка/порядка). Инициируйте эту коллекцию с результатом запроса при первом запуске, а для других вызовов просто установите результат из памяти. – alexey28

0

Несколько вопросов

  1. Как долго это берет, если запрос БД напрямую. Другой проблемой может быть задержка ASYNC_NETWORK_IO между хостом приложения и БД.

  2. сделал вам проверить это без использования Spring

+0

Прости, что я думал, что у меня это есть, но я этого не делаю. Я не думаю, что это так, но как я могу проверить ASYNC_NETWORK_IO? – ControlAltDel

+0

SQLServer предоставляет DMVs для запроса типов wait, как здесь: http://www.confio.com/db-resources/sql-wait-types/async-network-io/, но я не знаю, что эквивалентно в mysql.Вы проверяли, сколько времени потребуется, если вы запрашиваете прямо с консоли? Это должно дать вам полное представление о том, является ли клиентское приложение проблемой. Затем вы можете проверить, вызывает ли Сеть или весна проблему – Chandra

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