повышение скорости обработки запросов - PullRequest
0 голосов
/ 24 августа 2010

возникли серьезные проблемы с временем обработки моего запроса :( Я думаю, это потому, что запрос перекомпилируется каждый раз. но я не вижу возможности обойти это. следующий запрос / фрагмент кода:

private void readPerformance(String startTime, String endTime,
        String performanceTable, String interfaceInput) throws SQLException, IOException {
    String interfaceId, iDescp, iStatus = null;
    String dtime, ingress, egress, newLine, append, routerId= null;
    StringTokenizer st = null;
    stmtD = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,  
            java.sql.ResultSet.CONCUR_READ_ONLY);
    stmtD.setFetchSize(Integer.MIN_VALUE); 
    BufferedReader interfaceRead = new BufferedReader(new FileReader(interfaceInput));
    BufferedWriter pWrite = new BufferedWriter(new FileWriter("performanceInput.txt"));

    while((newLine = interfaceRead.readLine())!= null){
        st = new StringTokenizer(newLine,",");
        while(st.hasMoreTokens()){
            append = st.nextToken()+CSV+st.nextToken()+st.nextToken()+CSV+st.nextToken();
            System.out.println(append +" ");
            iStatus = st.nextToken().trim();
            interfaceId = st.nextToken().trim();
            append = append + CSV+iStatus+CSV+interfaceId;
            System.out.println(append +" ");
            pquery = " Select d.dtime,d.ifInOctets, d.ifOutOctets from "+performanceTable+"_1_60" +" AS d Where d.id = " +interfaceId 
            + " AND dtime BETWEEN " +startTime+ " AND "+ endTime;
            rsD = stmtD.executeQuery(pquery); 
            /* interface query*/
            while(rsD.next()){
                            dtime = rsD.getString(1);
                    ingress= rsD.getString(2);
                    egress = rsD.getString(3);
                    pWrite.write(append + CSV + dtime+CSV+ingress+CSV+egress+NL);

            }//end while
        }//end while
    }// end while

    pWrite.close();
    interfaceRead.close();
    rsD.close() ;   
    stmtD.close();

}

мое значение interfaceId постоянно меняется. поэтому я поместил запрос в цикл, что привело к повторной компиляции запроса несколько раз.

есть ли какой-нибудь способ лучше? Могу ли я подать в суд на хранимую процедуру в Java? если так как? не очень разбираюсь в этом.

текущее время обработки составляет почти 60 минут (: (() !!! Время создания текстового файла превышает 300 МБ Пожалуйста, помогите !!!

Спасибо.

Ответы [ 3 ]

1 голос
/ 24 августа 2010

Требуется больше информации, но я могу предложить некоторые общие вопросы / предложения.Это может не иметь ничего общего с компиляцией плана запроса (что было бы необычно)

  • Индексируются ли столбцы id и dtime?
  • Сколько раз выполняется запросза 60 минут?
  • Сколько времени занимает каждый запрос?

Если время на запрос велико, то проблема заключается в самом выполнении запроса, а не в его компиляции.Проверьте индексы, как описано выше.

Если существует много, много запросов, то причиной может быть именно объем запросов.Использование PreparedStatement (см. Ответ mdma) может помочь.Или же вы можете попробовать пакетные идентификаторы интерфейсов, которые вы хотите, используя оператор «in» и выполняя запрос для каждых 100 идентификаторов интерфейса, а не для каждого.

РЕДАКТИРОВАТЬ: В качестве хорошей практики ВСЕГДА следует использовать PreparedStatementтак как он будет правильно обрабатывать типы данных, такие как даты, чтобы вам не пришлось беспокоиться о форматировании их в правильный синтаксис SQL.Также предотвращает внедрение SQL.

1 голос
/ 24 августа 2010

Вы можете использовать PreparedStatement и параметры, которые могут избежать перекомпиляции запроса. Поскольку performanceTable является константой, это можно вставить в подготовленный запрос. Остальные переменные, используемые в условии WHERE, задаются как параметры.

Вне цикла создайте подготовленный оператор, а не обычный оператор:

   PreparedStatement stmtD = conn.prepareStatement(
         "Select d.dtime,d.ifInOctets, d.ifOutOctets from "+performanceTable+"_1_60 AS d"+ 
         " Where d.id = ? AND dtime BETWEEN ? AND ?");

Затем, в вашем цикле, установите параметры:

   stmtD.setInteger(1, interfaceID);
   stmtD.setInteger(2, startTime);
   stmtD.setInteger(3, endTime);
   ResultSet rsD = stmtD.executeQuery();  // note no SQL passed in here

Может быть хорошей идеей также проверить план запроса из MySQL с помощью EXPLAIN, чтобы увидеть, является ли это также узким местом. Кроме того, в функции происходит довольно много конкатенации диагностических строк. Как только запрос заработает, удаление может также повысить производительность.

Наконец, обратите внимание, что даже если запрос быстрый, сетевая задержка может замедлить работу. JDBC обеспечивает пакетное выполнение нескольких запросов, чтобы помочь уменьшить общую задержку на оператор. См. AddBatch / executeBatch для подключения.

0 голосов
/ 24 августа 2010

Судя по всему, вы запускаете несколько запросов на выборку (даже 100 в зависимости от размера вашего файла) Вместо этого из входного файла создайте список всех значений interfaceId, разделенных запятыми, а затем выполните 1 вызов SQL, используя ключевое слово «IN». Вы знаете, что показатели performanceTable, startTime и endTime не меняются, поэтому запрос будет выглядеть примерно так

SELECT d.dtime,d.ifInOctets, d.ifOutOctets 
FROM MyTable_1_60 as d 
WHERE dtime BETWEEN '08/14/2010' AND '08/15/2010'
AND d.id IN ( 10, 18, 25, 13, 75 ) 

Тогда вы можете открыть свой файл, сбросить результирующий набор одним махом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...