簡體   English   中英

PHP PDO Mysql插入性能

[英]PHP PDO Mysql Insert Performance

我通常不會在PHP中使用很多SQL東西,但是最近我被一位朋友強迫使用它來幫助他調試某些東西。

我在PHP中使用PDO插入一些數據,但是插入性能卻很糟糕。 一個簡單的151次插入循環需要將近6秒鍾! 我不知道為什么。

這是我的代碼:

<?php

$database='XXXXXX';
$username='XXXXXX';
$password='XXXXXX';
$hostname='127.0.0.1';

$inserted=0;
$counted=0;
$dsn = 'mysql:dbname='.$database.';host='.$hostname.'';
$start=microtime(true);
try {
    $data = new PDO($dsn, $username, $password, array(PDO::ATTR_EMULATE_PREPARES => false));
} catch (PDOException $e) {
    echo('Connection failed: ' . $e->getMessage());
}
for($i=1;$i<=150;$i++) {
    $time=time();
    $query=$data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
    $query->execute(array($i, $time));
}
$data=null;
print "Took: ".(microtime(true)-$start)." S to insert $i records\n";

// Took: 5.569482088089 S to insert 151 records <--- result
?>

我也使用bindParam嘗試了相同的代碼,並且速度大致相同。 該服務器具有8核Xeon處理器和64GB RAM。 該腳本是從命令行(php-cgi)運行的,數據庫和表是新的並且為空。 數據庫類型為InnoDB。 誰能指出我為什么會這么慢的正確方向? 因為我敢肯定MySQL從來沒有這么慢!

找到了這個。 PDO / PHP / MySQL中的性能:事務與直接執行 所以嘗試這個。

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
try {
        $data->beginTransaction();
        for($i=0; $i < 150; $i++) {
            $time = time();
            $query->bindValue(1, $i, PDO::PARAM_INT);
            $query->bindValue(2, $time, PDO::PARAM_STR);
            $query->execute();
        }
        $data->commit();
    } catch(PDOException $e) {
            $data->rollBack();
    }

事實證明,SQL服務器內部的設置是引起它的原因。 據我所知,在每次寫操作時,事務提交已設置為刷新到磁盤:

innodb_flush_log_at_trx_commit=0

這是新安裝的默認ACID兼容設置。

我將設置更改為此

innodb_flush_log_at_trx_commit=2

這僅允許斷電或OS崩潰來擦除事務緩沖區/日志,而不是mysqld崩潰。

對於某些需要ACID的“ D”為100%真實的人,則應保留此設置。

正如西蒙(Simon)在評論中所說,在循環中沒有任何准備工作。 這樣做將導致向數據庫發送300個查詢,每次查詢一次進行准備,然后進行實際插入。 之前使用prepare語句將僅導致151個查詢:

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
for ($i = 1; $i <= 150; $i++) {
    $time = time();
    $query->execute(array($i, $time));
}

另一個想法可能是使用組合的多插入語句。 我想它可能會有更好的性能,但我不確定:

$query = 'INSERT INTO `tbl_temp` (aid, bid) VALUES';
for ($i = 1; $i <= 150; $i++) {
    if ($i == 1) {
        $query .= ' ('.$i.', '.time().')';
    } else {
        $query .= ', ('.$i.', '.time().')';
    }
}
$data->exec($query);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM