Медленная производительность MySql

Я пытаюсь выполнить работу с системой, которую я создаю, и это очень медленно, и я не знаю, почему, или если это должно быть так медленно. Я тестирую, сколько одиночных INSERT я могу сделать с базой данных, и я получаю около 22 в секунду. Это звучит очень медленно, и когда я пытался делать вставки большого синтаксиса SQL, я могу вставить 30000 записей за 0,5 секунды. В реальной жизни вставки создаются разными пользователями в системе, поэтому накладные расходы на соединение, отправку запроса, разбор запроса и т. Д. Всегда будут там. То, что я пробовал до сих пор:

  • mysqli с минимальным количеством кода. = 22 ВСТАВКА в секунду
  • PDO с минимальным количеством кода. = 22 ВСТАВКА в секунду
  • Изменение хоста подключения с localhost на 127.0.0.1 = 22 INSERT в секунду
  • mysqli без объекта-оператора и проверка на SQL-injection = 22 INSERT в секунду

Так что что-то швы ошибаться здесь.

Системные спецификации:

  • Intel i5
  • 16 гигабайт
  • 7200 об / мин diskdrive

Программного обеспечения:

  • Windows 10
  • XAMPP, довольно новый с MariaDB
  • DB двигатель innoDB.

Код, который я использовал для проведения тестов:

$amountToInsert = 1000; //$fakeData is an array with randomly generated emails $fakeData = getFakeData($amountToInsert); $db = new DatabaseHandler(); for ($i = 0; $i < $amountToInsert; $i++) { $db->insertUser($fakeUsers[$i]); } $db->closeConnection(); 

Класс, который вызывает базу данных:

 class DatabaseHandler { private $DBHOST = 'localhost'; private $DBUSERNAME = 'username'; private $DBPASSWORD = 'password'; private $DBNAME = 'dbname'; private $DBPORT = 3306; private $mDb; private $isConnected = false; public function __construct() { $this->mDb = new mysqli($this->DBHOST, $this->DBUSERNAME , $this->DBPASSWORD, $this->DBNAME , $this->DBPORT); $this->isConnected = true; } public function closeConnection() { if ($this->isConnected) { $threadId = $this->mDb->thread_id; $this->mDb->kill($threadId); $this->mDb->close(); $this->isConnected = false; } } public function insertUser($user) { $this->mDb->autocommit(true); $queryString = 'INSERT INTO `users`(`email`, `company_id`) ' .'VALUES (?, 1)'; $stmt = $this->mDb->prepare($queryString); $stmt->bind_param('s', $user); if ($stmt->execute()) { $stmt->close(); return 1; } else { $stmt->close(); return 0; } } } 

Таблица «user» имеет 4 столбца со следующей структурой:

  • id INT первичный ключ без знака
  • электронная почта VARCHAR (60)
  • company_id INT unsigned INDEX
  • guid TEXT

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

Related of "Медленная производительность MySql"

Как это объясняется в комментариях, это InnoDB виноват. По умолчанию этот движок слишком осторожен и не использует кеш диска, чтобы убедиться, что данные действительно были записаны на диск, прежде чем вы получите сообщение об успешном завершении. Таким образом, у вас в основном есть два варианта.

  1. Большую часть времени вы просто не заботитесь о подтвержденной записи. Таким образом, вы можете настроить mysql, установив этот параметр mysql равным нулю:

     innodb_flush_log_at_trx_commit = 0 

    пока он настроен таким образом, ваши записи InnoDB будут почти такими же быстрыми, как MyISAM.

  2. Другой вариант – перенос всех ваших записей в одну транзакцию. Поскольку для всех записей потребуется только одно подтверждение, это тоже будет разумно быстро.

Разумеется, это просто разумно подготовить ваш запрос только один раз с несколькими вставками, но прирост скорости пренебрежимо мал по сравнению с проблемой выше. Поэтому он не учитывается ни как объяснение, ни как средство правовой защиты для такой проблемы.

Ваш тест не очень хороший способ оценки производительности. Почему, потому что вы готовите заявление 1000 раз. Это не значит, что должны использоваться подготовленные заявления. Заявление готовится один раз, а разные параметры связаны несколько раз. Попробуй это:

 public function __construct() { $this->mDb = new mysqli($this->DBHOST, $this->DBUSERNAME , $this->DBPASSWORD, $this->DBNAME , $this->DBPORT); $this->isConnected = true; $queryString = 'INSERT INTO `users`(`email`, `company_id`) ' .'VALUES (?, 1)'; $this->stmt_insert = $this->mDb->prepare($queryString); } 

а также

 public function insertUser($user) { $this->stmt_insert->bind_param('s', $user); if ($this->stmt_insert->execute()) { return 1; } else { return 0; } } 

И вы увидите огромный рост производительности. Итак, чтобы повторить, нет ничего плохого в вашей системе, это просто тест, который был плохим.

Обновить:

В вашем здравом смысле есть смысл заранее подготовиться и повторно использовать подготовленное заявление, не придавая большого значения. Я тестировал и обнаружил, что он составляет около 5-10%

однако, есть что-то, что действительно дает большой толчок. Превращение Autocommit в off !. Вставка 100 записей, которые раньше занимали около 4,7 секунды, в среднем упала до <0,5 с в среднем!

$ Con-> автокоммит (ложь);

/ loop / $ con> commit ();