Производительность чтения JDBC и MySQL - PullRequest
3 голосов
/ 27 августа 2010

У меня действительно большая проблема.Я использую MySQL для хранения предложений с тегами части речи в таблице.Таблица выглядит следующим образом:

+------------+------------------+------+-----+---------+-------+
| Field      | Type             | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| idTitle    | varchar(25)      | NO   | PRI | NULL    |       |
| idReview   | int(10) unsigned | NO   | PRI | NULL    |       |
| idSentence | int(10) unsigned | NO   | PRI | NULL    |       |
| content    | text             | NO   |     | NULL    |       |
| POSInfo    | text             | YES  |     | NULL    |       |
+------------+------------------+------+-----+---------+-------+

Это индексы в таблице:

+-----------------+------------+-----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table           | Non_unique | Key_name                    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------------+------------+-----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| reviewsentences |          0 | PRIMARY                     |            1 | idSentence  | A         |          23 |     NULL | NULL   |      | BTREE      |         |
| reviewsentences |          0 | PRIMARY                     |            2 | idTitle     | A         |       32087 |     NULL | NULL   |      | BTREE      |         |
| reviewsentences |          0 | PRIMARY                     |            3 | idReview    | A         |     2470720 |     NULL | NULL   |      | BTREE      |         |
| reviewsentences |          1 | fk_ReviewSentences_Reviews1 |            1 | idTitle     | A         |         983 |     NULL | NULL   |      | BTREE      |         |
| reviewsentences |          1 | fk_ReviewSentences_Reviews1 |            2 | idReview    | A         |      494144 |     NULL | NULL   |      | BTREE      |         |
+-----------------+------------+-----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

Я пытаюсь прочитать рецензии, которые относятся к определенному рецензированию, и добавить их вобъект обзора.Я получаю доступ к базе данных через JDBC, и чтение занимает вечность!Я говорю 2 минуты на 26 строк!Это код Java, который я использую для запроса к базе данных:

public List<Review> fillupReviews(List<Review> reviews, boolean tagged){

    try {
        Statement stmt = dbConnection.createStatement() ;


        for (Review review : reviews) {
            ResultSet rs=null;
            if(tagged==true){
                rs = stmt.executeQuery("SELECT idSentence, POSInfo FROM reviewsentences WHERE idTitle="+review.getMovieID()+" and idReview="+review.getReviewID()+";") ;
            }else{
                rs = stmt.executeQuery("SELECT idSentence, content FROM reviewsentences WHERE idTitle="+review.getMovieID()+" and idReview="+review.getReviewID()+";") ;
            }

            while(rs.next()){
                review.addTaggedSentence(rs.getInt(1),rs.getString(2));
            }
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }

    return reviews;
}

Если я получаю доступ к той же таблице с тем же запросом через MySQL Workbench, это займет 0,296 секунды ??Так что я думаю, что должно быть что-то серьезно не так!Но я действительно не могу видеть, что идет не так или что изменить, чтобы ускорить эту чертову вещь.Пожалуйста, может кто-нибудь дать мне подсказку?

Это снова я, я наконец нашел решение!Называется подготовленным заявлением !!<- кто бы мог догадаться !?Вот код: </p>

public List<Review> fillupReviews(List<Review> reviews, boolean tagged){

        try {

            PreparedStatement selectReview=null;
            if(tagged==true){
                selectReview = dbConnection.prepareStatement("SELECT idSentence, POSInfo FROM reviewsentences WHERE idTitle= ? AND idReview= ?;");
            }else{
                selectReview = dbConnection.prepareStatement("SELECT idSentence, Content FROM reviewsentences WHERE idTitle= ? AND idReview= ?;");
            }

            for (Review review : reviews) {

                selectReview.setString(1, review.getMovieID());
                selectReview.setInt(2, review.getReviewID());

                ResultSet rs = selectReview.executeQuery();

                while(rs.next()){
                    review.addTaggedSentence(rs.getInt(1),rs.getString(2));
                }
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return reviews;
    } 

Теперь эта дырка работает как ад (почти так же быстро, как MySQL Workbench [0,3 сек]).Что я не совсем понимаю, почему нормальное утверждение так медленно?У кого-нибудь есть объяснение этому?

Ответы [ 5 ]

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

Во-первых, вы рассчитываете только этот вызов метода?

Где вы получаете соединение с БД, вы рассчитываете только время для выполнения запроса или время для получения соединения?

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

Несмотря на то, что это не должно занять много времени, что-то не так, я подозреваю, что с вашей настройкой соединения может быть способ, которым java находит mysql (локально, вы используете dns и т. Д.).

Также я бы использовал подготовленные заявления, они более безопасны и лучше работают.

Также, какой драйвер вы используете?

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

Прежде всего. Можете ли вы дать конкретную информацию о том, какая часть вашего кода занимает 2m ++. Это в операторе stmt.executeQuery (String) или другой части?

Я сам столкнулся с этой проблемой в большой и большой СУБД. Но мои данные были больше, чем 150K. К сожалению, у меня нет готового решения вашей проблемы. Но есть некоторые следы того, что я сделал.

  1. Я пытался переключиться с водителя на водителя. Пожалуйста, имейте в виду, что некоторые драйверы могут работать быстрее, но он просит вас пожертвовать переносимостью.
  2. Я попытался переключиться с жестко запрограммированного соединения на пул соединений. К сожалению, это не очень помогло.
  3. Я пытался не использовать предложение "ГДЕ" в поле VARCHAR.
  4. Я пытался проиндексировать какое-то поле, которое я часто "ГДЕ" d
  5. Я пытался использовать подготовленное выражение только для того, чтобы СУБД не переэшировала тот же запрос.

Есть и другие вещи, но я думаю, что они специфичны для DMBS.

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

Похоже, у вас 2470720 отзывов.По сравнению с локальным запуском в Mysql Workbench, удаленный запуск (в вашем коде), безусловно, потребует больше времени для запроса, возврата и передачи такого количества значений.

Mysql workbench, вероятно, извлекает количество результатов и разбивает на страницы то, что он даетвы - только возвращаете результаты по мере необходимости;Кроме того, ваше рабочее место может включать сжатие в соединении, а JDBC - нет, создавая тем самым еще более быстрое соединение.

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

Комментарий из review.addTaggedSentence(rs.getInt(1),rs.getString(2)); Это все еще занимает столько времени?

Вы не закрываете ResultSet, вам нужно сделать rs.close() после того, как ваш while(rs.next()) завершен.

Распечатайте фактический SQL, который вы используете в Java - вы на 100% уверены, что это тот же самый запрос, который вы выполняете в рабочей среде MySQL?

Вы также выполняете запрос в for (Review review : reviews), так сколько же запросов выполняется?

Вы не говорите нам, что занимает 2,36, мин. так что - профилируйте или выполните несколько простых System.out.println () в вашем java-приложении, чтобы вы точно знали, какой SQL вы на самом деле используете и сколько из них запускается.

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

Если это локальный сервер MySQL, то я постараюсь прокомментировать выборку MySQL и заменить ее фиктивным кодом для проверки производительности вашего кода (не забывайте использовать yout GetMovieId () и т.д.).

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