Исследование медленных простых запросов в JDBC и MySQLJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Исследование медленных простых запросов в JDBC и MySQL

Сообщение Anonymous »

Код: Выделить всё

PreparedStatement.executeQuery()
выполняется примерно в 20 раз дольше, чем если бы он запускался непосредственно через оболочку. Я зарегистрировался с помощью таймеров, чтобы определить, что виноват этот метод.
Запрос и некоторая информация о БД (на данный момент игнорируем проблему Java):< /p>

Код: Выделить всё

mysql> SELECT username from users where user_id = 1;
// молниеносно
Выполнение одного и того же запроса 1000 раз через mysqlslap также молниеносно.

Код: Выделить всё

mysqlslap --create-schema=mydb --user=root -p --query="select username from phpbb_users where user_id = 1" --number-of-queries=1000 --concurrency=1

Benchmark
Average number of seconds to run all queries: 0.051 seconds
Minimum number of seconds to run all queries: 0.051 seconds
Maximum number of seconds to run all queries: 0.051 seconds
Number of clients running queries: 1
Average number of queries per client: 1000
Проблема: Выполнение того же запроса в JDBC значительно замедляет работу. В цикле for вызов приведенного ниже запроса queryUsername() 1000 раз (это вызывается в методе Main, который здесь не показан) занимает около 872 мс. Это примерно в 17 раз медленнее! Я отследил интенсивное использование, разместив таймеры в разных местах (некоторые опустил для краткости). Основным подозреваемым является stmt.executeQuery(), выполнение которого заняло 776 мс из 872 мс.

Код: Выделить всё

public static String queryUsername() {
String username = "";
// DBCore.getConnection() returns HikariDataSource.getConnection() implementation exactly as per https://www.baeldung.com/hikaricp
try (Connection connection = DBCore.getConnection();
PreparedStatement stmt = connection.prepareStatement("SELECT username from phpbb_users where user_id = ?");) {
stmt.setInt(1, 1);  // just looking for user_id 1 for now
// Google timer used to measure how long executeQuery() is taking
// Another Timer is used outside of this method call to see how long
// total execution takes.
// Approximately 1 second in for loop calling this method 1000 times
Stopwatch s = Stopwatch.createStarted();
try (ResultSet rs = stmt.executeQuery();) {
s.stop(); // stopping the timer after executeQuery() has been called
timeElapsed  += s.elapsed(TimeUnit.MICROSECONDS);
while (rs.next())
{
username = rs.getString("username"); // the query returns 1 record
}
}
} catch (SQLException e) {
e.printStackTrace();
}

return username;
}
Дополнительный контекст и проверенные варианты:

[img]https:// i.sstatic.net/qeoCW.png[/img]


Изображение
  • Код: Выделить всё

    SHOW OPEN TABLESВ 
    открыто несколько таблиц, но у всех есть In_use=0 и Name_locked=0.
  • Код: Выделить всё

    SHOW FULL PROCESSLIST
    выглядит исправно.
  • user_id — это индексированный первичный ключ.
  • Сервер представляет собой одноядерный сервер Upcloud стоимостью 5 долларов в месяц и 1 ГБ ОЗУ. Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-66-generic x86_64). Mysql версии 8.0.23-0ubuntu0.20.04.1 для Linux на x86_64 ((Ubuntu))
  • Драйвер JDBC — mysql-connector-java_8.0.23.jar, полученный из mysql- разъем-java_8.0.23-1ubuntu20.04_все через https://dev.mysql.com/downloads/connector/j/
[img]https:// i.sstatic.net/KoBFD.png[/img]


Подробнее здесь: https://stackoverflow.com/questions/664 ... -and-mysql
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»