Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
199 views
in Technique[技术] by (71.8m points)

php - Slow performance MySql

I'm trying out performance of a system I'm building, and it's really slow, and I don't know why or if it should be this slow. What I'm testing is how many single INSERT I can do to the database and I get around 22 per second. That sounds really slow and when I tried to do the inserts i a singel big SQL-query I can insert 30000 records in about 0.5 seconds. In real life the inserts is made by different users in the system so the overhead of connecting, sending the query, parsing the query etc. will always be there. What I have tried so far:

  • mysqli with as little code as possible. = 22 INSERT per second
  • PDO with as little code as possible. = 22 INSERT per second
  • Changing the connection host from localhost to 127.0.0.1 = 22 INSERT per second
  • mysqli without statement object and check for SQL-injection = 22 INSERT per second

So something seams to be wrong here.

System specs:

  • Intel i5
  • 16 gig ram
  • 7200 rpm diskdrive

Software:

  • Windows 10
  • XAMPP, fairly new with MariaDB
  • DB engine innoDB.

The code I used to do the tests:

$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();

The class that calls the database:

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;
        }
    }
}

The "user" table has 4 columns with the following structure:

  • id INT unsigned primary key
  • email VARCHAR(60)
  • company_id INT unsigned INDEX
  • guid TEXT

I'm at a loss here and don't really know where to look next. Any help in the right direction would be very much appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Like it's explained in the comments, it's InnoDB to blame. By default this engine is too cautious and doesn't utilize the disk cache, to make sure that data indeed has been written on disk, before returning you a success message. So you basically have two options.

  1. Most of time you just don't care for the confirmed write. So you can configure mysql by setting this mysql option to zero:

    innodb_flush_log_at_trx_commit = 0
    

    as long as it's set this way, your InnoDB writes will be almost as fast as MyISAM.

  2. Another option is wrapping all your writes in a single transaction. As it will require only single confirmation from all the writes, it will be reasonable fast too.

Of course, it's just sane to prepare your query only once with multiple inserts but the speed gain is negligible compared to the issue above. So it doesn't count neither as an explanation nor as a remedy for such an issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...