繁体   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