В последней статье говорилось о нескольких однопоточных методах стресс-тестирования записи MySQL. Изначально я хотел представить некоторые идеи, но просто поделился личным опытом и идеями. Позже фанат оставил сообщение в фоновом режиме и захотел узнать, как бороться с параллелизмом, поэтому сегодня я написал эту статью.
Параллелизм широко используется при тестировании производительности. По моему личному опыту, параллелизм используется практически во всех стресс-тестах. Теперь позвольте мне рассказать об использовании параллелизма в тестировании производительности записи MySQL.
первый,Нам нужно выяснить проблему: одновременно объект. Для реальной ситуации в MySQLtest,я перечислил3индивидуальныйодновременнообъект:java.sql.Statement
、 java.sql.Connection
а также database
。
Начну с самопроверки максимального количества строк, записываемых в секунду: 50w. Если я еще раз оптимизирую программу, оно должно быть выше, но по результатам теста оно будет ненамного выше. Грубая оценка в пределах 1 миллиона.
Давайте сначала проведем Контрольный показатель,Потому что мой компьютер уже в состоянии Шрёдингера,производительность очень нестабильна. Для простой и быстрой демонстрации того, как его использовать.,На этот раз я использовал фиксированный sql.
Примеры использования следующие:
package com.funtest.temp
import com.funtester.db.mysql.FunMySql
import com.funtester.frame.SourceCode
class MysqlTest extends SourceCode {
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
String sql = "insert into user (name, age, level, region, address) values ('FunTester', 23, 2, «глобальная деревня», 'Восемь пар')";
String ipPort = "127.0.0.1:3306";// Адрес сервера
String database = "funtester"// Адрес сервера
String user = "root";// имя пользователя
String password = "funtester";// пароль
def base = new FunMySql(ipPort, database, user, password);// Создать базовый класс операций с базой данных
def statement = base.connection.createStatement();// создавать SQL объект утверждения
while (true) {
statement.executeUpdate(sql);// Выполнить оператор вставки
}
statement.close();// Закрыть ресурс
base.close();// Закрыть ресурс
}
}
Результаты испытаний следующие:
количество строк | количество секунд |
---|---|
9826 | 36 |
10278 | 37 |
10208 | 38 |
10220 | 39 |
9802 | 40 |
8975 | 41 |
9957 | 42 |
9412 | 43 |
9884 | 44 |
9412 | 45 |
9640 | 46 |
10304 | 47 |
Видно, что результаты намного лучше, чем результаты предыдущих тестов. Теперь каждый сможет понять производительность моего компьютера по методу Шрёдингера. |
обсуждалось ранее Statement
Фактически, в сценарии запроса параллелизм не поддерживается. Исходный код также был проанализирован. Заинтересованные студенты могут прочитать исходную статью. Причины не будут повторяться. Что касается сценария написания, то соответствующего исходного кода нет. Для простоты мы его непосредственно протестировали.
Ниже приведен пример использования:
package com.funtest.temp
import com.funtester.db.mysql.FunMySql
import com.funtester.frame.SourceCode
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MysqlTest extends SourceCode {
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
String sql = "insert into user (name, age, level, region, address) values ('FunTester', 23, 2, «глобальная деревня», 'Восемь пар')";
String ipPort = "127.0.0.1:3306";// Адрес сервера
String database = "funtester"// Адрес сервера
String user = "root";// имя пользователя
String password = "funtester";// пароль
def base = new FunMySql(ipPort, database, user, password);// Создать базовый класс операций с базой данных
def statement = base.connection.createStatement();// создавать SQL объект утверждения
ExecutorService executors = Executors.newFixedThreadPool(10);// создать пул потоков
10.times {
executors.execute {// 10 тем
while (true) {
statement.executeUpdate(sql);// осуществлять SQL заявление
}
}
} statement.close();// Закрыть ресурс
base.close();// Закрыть ресурс
}
}
Просто используйте 10 потоков, чтобы запустить и посмотреть. Результат следующий:
количество строк | время |
---|---|
9584 | 42 |
10263 | 43 |
10098 | 44 |
9744 | 45 |
8864 | 46 |
9019 | 47 |
10133 | 48 |
9768 | 49 |
9613 | 50 |
9886 | 51 |
9835 | 52 |
6585 | 53 |
Видно, что особой разницы нет. Во время теста не было зарегистрировано никаких ошибок, что указывает на то, что Statement может поддерживать параллелизм, но фактический эффект не очевиден. |
Далее мы будем Connection
Для параллелизма каждый поток создает Statement
Это решение спроектировано так, чтобы быть простым и избегать взаимного вмешательства. Это хорошая стратегия изоляции.
Вариант использования следующий:
import com.funtester.db.mysql.FunMySql
import com.funtester.frame.FunPhaser
import com.funtester.frame.SourceCode
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MysqlTest extends SourceCode {
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
String sql = "insert into user (name, age, level, region, address) values ('FunTester', 23, 2, «глобальная деревня», 'Восемь пар')";
String ipPort = "127.0.0.1:3306";// Адрес сервера
String database = "funtester"// Адрес сервера
String user = "root";// имя пользователя
String password = "funtester";// пароль
def base = new FunMySql(ipPort, database, user, password);// Создать базовый класс операций с базой данных
ExecutorService executors = Executors.newFixedThreadPool(10);// создать пул потоков
def phaser = new FunPhaser()// создавать Phaser 10.times {
phaser.register()// Зарегистрировать тему
executors.execute {// 10 тем
def statement = base.connection.createStatement();// создавать SQL объект утверждения
while (true) {
statement.executeUpdate(sql);// осуществлять SQL заявление
}
phaser.done()// Завершить тему
}
} executors.shutdown();// Закрыть пул потоков
phaser.await()// Подождите, пока все темы, которые интересуют, закончатся.
base.close();// Закрыть ресурс
}
}
Результаты испытаний следующие:
количество строк | время |
---|---|
10193 | 57 |
10095 | 58 |
9952 | 59 |
9991 | 0 |
9893 | 1 |
9880 | 2 |
8195 | 3 |
7834 | 4 |
8695 | 5 |
8633 | 6 |
9078 | 7 |
8613 | 8 |
Видно, что производительность пока средняя, почти такая же. |
Дальше мы продолжим database
уровни параллелизма, создавая больше Connection
для достижения желаемой лучшей производительности записи.
количество строк | время |
---|---|
38549 | 32 |
43925 | 33 |
32172 | 34 |
44419 | 35 |
42545 | 36 |
40741 | 37 |
34487 | 38 |
47211 | 39 |
43269 | 40 |
45396 | 41 |
36748 | 42 |
Производительность сразу пошла вверх. |
Давайте повторим метод с самой высокой однопоточной производительностью — вставку слов в N строк — и протестируем его еще раз. Результаты следующие:
количество строк | время |
---|---|
241440 | 12 |
250660 | 13 |
252880 | 14 |
246870 | 15 |
242760 | 16 |
214790 | 17 |
257260 | 18 |
250010 | 19 |
251720 | 20 |
Ощущается ли это так? MySQL
Соответствует ли производительность записи требованиям?
В реальной работе сценарий будет более сложным, и на производительность записи влияет множество факторов. Как и в первых двух случаях, хотя теоретически производительность будет значительно улучшена, фактические результаты почти такие же, вероятно, потому, что один Connection
узкое место в производительности.
На производительность записи MySQL влияет множество факторов. Помимо аппаратного обеспечения, я кратко перечислю некоторые из них.
На производительность записи MySQL влияет множество факторов. Понимание и оптимизация этих факторов может значительно повысить эффективность записи в базу данных. Вот некоторые из основных влияющих факторов:
Конфигурация базы данных
В реальных сценариях для разных факторов применяются разные стратегии, а техническая мощь повышается за счет непрерывного обучения.